如何理解Java中的隐藏与覆盖

java的重载、覆盖和隐藏的区别

http://blog.csdn.net/yangquanhui1991/article/details/49679557

重载:方法名相同,但参数不同的多个同名函数。

发生在子类于父类之间,是指在子类与父类之间或在同一类中定义具有相同的方法名,访问权限等的方发。

区别在于返回类型或参数列表。

注意:1.参数不同的意思是参数类型、参数个数、参数顺序至少有一个不同

     2.返回值和异常以及访问修饰符,不能作为重载的条件(因为对于匿名调用,会出现歧义,eg:void a ()和int a() ,如果调用a(),出现歧义)

     3.main方法也是可以被重载的

覆盖:子类重写父类的方法,要求方法名和参数类型完全一样(参数不能是子类),返回值和异常比父类小或者相同(即为父类的子类),访问修饰符比父类大或者相同。

两同两小一大

发生在子类与父类的之间,指在在子类中声明一个和父类具有相同的方法名,参数列表,返回值,访问权限等的方法,即在子类中重新编写方法实现的功能。

覆盖不同于静态方发的隐藏,父类中被隐藏的方法在子类中完全不可用,而父类中被覆盖的方法在子类中可以通过其他方式被引用。

注意:子类实例方法不能覆盖父类的静态方法;子类的静态方法也不能覆盖父类的实例方法(编译时报错),总结为方法不能交叉覆盖

隐藏:父类和子类拥有相同名字的属性或者方法时,父类的同名的属性或者方法形式上不见了,实际是还是存在的。

隐藏现象发生在子类和父类之间,隐藏是针对父类中成员变量和静态方法而言。

当子类声明与父类中成员变量具有相同的变量名的变量时,则实现了对父类中成员变量的隐藏;

当子类声明了与父类中的静态成员方法具有相同的方法名,参数列表和相同的返回值时,则实现了对父类中静态方法的隐藏。

 注意:当发生隐藏的时候,声明类型是什么类,就调用对应类的属性或者方法,而不会发生动态绑定

      方法隐藏只有一种形式,就是父类和子类存在相同的静态方法

 属性只能被隐藏,不能被覆盖

      子类实例变量/静态变量可以隐藏父类的实例/静态变量,总结为变量可以交叉隐藏

隐藏和覆盖的区别:

  被隐藏的属性,在子类被强制转换成父类后,访问的是父类中的属性

  被覆盖的方法,在子类被强制转换成父类后,调用的还是子类自身的方法

因为覆盖是动态绑定,是受RTTI(run time type identification,运行时类型检查)约束的,隐藏不受RTTI约束,总结为RTTI只针对覆盖,不针对隐藏

特殊情况:

  1.final修饰的属性可以被隐藏,但是不能被赋值,即不能用=来赋值,网上说final属性不能被修改,这个说法不准确,因为对于引用类型的变量用final修饰后,它只是不能被指向其他对象,但是可以改它自身的值,可以用ArrayList测试,final属性可以在运行的时候进行初始化,但是不能不出现初始化语句

  2.final修饰的方法不能被覆盖,可以被重载

  3.final修饰的类不能被继承

  4.private 方法隐式添加了final

实例:

SuperClass类:

[java] view plaincopy

  1. package com.yilong.test.scjp;  
  2. public class SuperClass {  
  3. public static int i = 1;  
  4. public int j = 2;  
  5. public final int k = 3;  
  6. public static void method1() {  
  7.        System.out.println("SuperClass Method1");  
  8.     }  
  9. public void method2() {  
  10.        System.out.println("SuperClass Method2");  
  11.     }  
  12. public final void method3() {  
  13.        System.out.println("SuperClass Method3");  
  14.     }  
  15. }  

SubClass类:

[java] view plaincopy

  1. package com.yilong.test.scjp;  
  2. public class SubClass extends SuperClass {  
  3. public static int i = 2;//无论是不是static,都能隐藏父类的变量i
  4. public static int j = 1;  
  5. public final int k = 4;//无论是不是final,都能隐藏父类的变量k
  6. public static void method1() {  
  7.        System.out.println("SubClass Method1");  
  8.     }  
  9. public void method2() {  
  10.        System.out.println("SubClass Method2");  
  11.     }  
  12. //Cannot override the final method from SuperClass
  13. /*public final void method3() {
  14.        System.out.println("SubClass Method3");
  15.     }*/
  16. public static void main(String[] args) {  
  17.        SuperClass sc = new SubClass();  
  18.        System.out.println("i = " + sc.i);  
  19.        System.out.println("j = " + sc.j);  
  20.        System.out.println("k = " + sc.k);  
  21.        sc.method1();//静态方法只能被隐藏
  22.        sc.method2();  
  23.        SubClass subc = new SubClass();  
  24.        System.out.println("i = " + subc.i);  
  25.        System.out.println("j = " + subc.j);  
  26.        System.out.println("k = " + subc.k);  
  27.        subc.method1();  
  28.        subc.method2();  
  29.     }  
  30. }  

打印结果:

i = 1 j = 2 k = 3 SuperClass Method1 SubClass Method2 i = 2 j = 1 k = 4 SubClass Method1 SubClass Method2

补充:

子类重写父类的方法时候,不能抛出与父类方法不同的异常。意味着:如果父类的方法抛出了异常,子类重写该方法时没有抛出异常是合法的;但是如果父类中的方法没有抛出异常,而子类重写该方法时抛出了异常,那么就会编译错误;

另外,如果子类在重写父类的方法的时候抛出的异常与父类方法中抛出的异常不一样,那么也是会编译错误的,如父类方法中抛出的是InterruptedException,而子类重写该方法时抛出的是Exception,那么也会编译错误。

版权声明:转载需标明博客来源:http://blog.csdn.net/yangquanhui1991 大家互相学习,一起进步!

http://blog.csdn.net/zhangchaokun/article/details/6776805

例子:

class Student1{  int math = 70;  static int computer = 80;  int english = 65;  public Student1(){     study();     exercise();  }  public void study(){      System.out.println("Student.study:每位学生都在认真学习");   }  public static void exercise(){     System.out.println("Student.exercise:所有学生都在做练习");  } }

class Graduate1 extends Student1{  int math = 93;  int computer = 99;  static int english = 85;  public Graduate1(){     study();     exercise();  }  public void study(){     System.out.println("Graduate.study:每位研究生都在认真学习");  }  public static void exercise(){     System.out.println("Graduate.exercise:所有研究生都在做练习");  }  public static void main() {   Student1 s = new Graduate1();   System.out.println();   Graduate1 g = new Graduate1();   System.out.print(s.math);   System.out.print("\t");   System.out.print(s.computer);   System.out.print("\t");   System.out.println(s.english);   System.out.print(g.math);   System.out.print("\t");   System.out.print(g.computer);   System.out.print("\t");   System.out.println(g.english);  } }

1. 隐藏与覆盖类方法

    在讲清这个问题之前,先明白什么是隐藏?什么是覆盖?

    所谓隐藏,是指运行时系统调用当前对象引用的编译时类型中定义的方法;对于覆盖,则指运行时系统调用当前对象引用运行时类型中定义的方法。

    所以在执行Student1 s = new Graduate1();和Graduate1 g = new Graduate1();时,(1)先进行Student1类的构造,这里包括两个方法study()和exercise(),由于study()方法被覆盖,所以先执行Graduate1里study(),再执行Student1里的exercise();(2)再进行Graduate1类的构造,同样包括两个方法study()和exercise(),所以执行顺序为先Graduate1里的study()方法,再Graduate1里的exercise()方法。 2. 隐藏与覆盖成员变量

    如果子类中的变量和父类中的变量具有相同的名字,那么子类中的变量就会隐藏父类中的变量,不管他们的类型是什么,也不管他们是类变量还是实例变量。

   所以在执行诸如System.out.print(s.math);之类的s实例的程序时,显示为Student1类的成员变量,而执行诸如System.out.print(g.math);之类的g实例的程序时,显示为Graduate1类的成员变量。

答案:

Graduate.study:每位研究生都在认真学习 Student.exercise:所有学生都在做练习 Graduate.study:每位研究生都在认真学习 Graduate.exercise:所有研究生都在做练习

Graduate.study:每位研究生都在认真学习 Student.exercise:所有学生都在做练习 Graduate.study:每位研究生都在认真学习 Graduate.exercise:所有研究生都在做练习 70 80 65 93 99 85

重载:方法名相同,但参数不同的多个同名函数。

发生在子类于父类之间,是指在子类与父类之间或在同一类中定义具有相同的方法名,访问权限等的方发。

区别在于返回类型或参数列表。

注意:1.参数不同的意思是参数类型、参数个数、参数顺序至少有一个不同

     2.返回值和异常以及访问修饰符,不能作为重载的条件(因为对于匿名调用,会出现歧义,eg:void a ()和int a() ,如果调用a(),出现歧义)

     3.main方法也是可以被重载的

覆盖:子类重写父类的方法,要求方法名和参数类型完全一样(参数不能是子类),返回值和异常比父类小或者相同(即为父类的子类),访问修饰符比父类大或者相同。

两同两小一大

发生在子类与父类的之间,指在在子类中声明一个和父类具有相同的方法名,参数列表,返回值,访问权限等的方法,即在子类中重新编写方法实现的功能。

覆盖不同于静态方发的隐藏,父类中被隐藏的方法在子类中完全不可用,而父类中被覆盖的方法在子类中可以通过其他方式被引用。

注意:子类实例方法不能覆盖父类的静态方法;子类的静态方法也不能覆盖父类的实例方法(编译时报错),总结为方法不能交叉覆盖

隐藏:父类和子类拥有相同名字的属性或者方法时,父类的同名的属性或者方法形式上不见了,实际是还是存在的。

隐藏现象发生在子类和父类之间,隐藏是针对父类中成员变量和静态方法而言。

当子类声明与父类中成员变量具有相同的变量名的变量时,则实现了对父类中成员变量的隐藏;

当子类声明了与父类中的静态成员方法具有相同的方法名,参数列表和相同的返回值时,则实现了对父类中静态方法的隐藏。

 注意:当发生隐藏的时候,声明类型是什么类,就调用对应类的属性或者方法,而不会发生动态绑定

      方法隐藏只有一种形式,就是父类和子类存在相同的静态方法

 属性只能被隐藏,不能被覆盖

      子类实例变量/静态变量可以隐藏父类的实例/静态变量,总结为变量可以交叉隐藏

隐藏和覆盖的区别:

  被隐藏的属性,在子类被强制转换成父类后,访问的是父类中的属性

  被覆盖的方法,在子类被强制转换成父类后,调用的还是子类自身的方法

因为覆盖是动态绑定,是受RTTI(run time type identification,运行时类型检查)约束的,隐藏不受RTTI约束,总结为RTTI只针对覆盖,不针对隐藏

特殊情况:

  1.final修饰的属性可以被隐藏,但是不能被赋值,即不能用=来赋值,网上说final属性不能被修改,这个说法不准确,因为对于引用类型的变量用final修饰后,它只是不能被指向其他对象,但是可以改它自身的值,可以用ArrayList测试,final属性可以在运行的时候进行初始化,但是不能不出现初始化语句

  2.final修饰的方法不能被覆盖,可以被重载

  3.final修饰的类不能被继承

  4.private 方法隐式添加了final

实例:

SuperClass类:

[java] view plaincopy

  1. package com.yilong.test.scjp;  
  2. public class SuperClass {  
  3. public static int i = 1;  
  4. public int j = 2;  
  5. public final int k = 3;  
  6. public static void method1() {  
  7.        System.out.println("SuperClass Method1");  
  8.     }  
  9. public void method2() {  
  10.        System.out.println("SuperClass Method2");  
  11.     }  
  12. public final void method3() {  
  13.        System.out.println("SuperClass Method3");  
  14.     }  
  15. }  

SubClass类:

[java] view plaincopy

  1. package com.yilong.test.scjp;  
  2. public class SubClass extends SuperClass {  
  3. public static int i = 2;//无论是不是static,都能隐藏父类的变量i
  4. public static int j = 1;  
  5. public final int k = 4;//无论是不是final,都能隐藏父类的变量k
  6. public static void method1() {  
  7.        System.out.println("SubClass Method1");  
  8.     }  
  9. public void method2() {  
  10.        System.out.println("SubClass Method2");  
  11.     }  
  12. //Cannot override the final method from SuperClass
  13. /*public final void method3() {
  14.        System.out.println("SubClass Method3");
  15.     }*/
  16. public static void main(String[] args) {  
  17.        SuperClass sc = new SubClass();  
  18.        System.out.println("i = " + sc.i);  
  19.        System.out.println("j = " + sc.j);  
  20.        System.out.println("k = " + sc.k);  
  21.        sc.method1();//静态方法只能被隐藏
  22.        sc.method2();  
  23.        SubClass subc = new SubClass();  
  24.        System.out.println("i = " + subc.i);  
  25.        System.out.println("j = " + subc.j);  
  26.        System.out.println("k = " + subc.k);  
  27.        subc.method1();  
  28.        subc.method2();  
  29.     }  
  30. }  

打印结果:

i = 1 j = 2 k = 3 SuperClass Method1 SubClass Method2 i = 2 j = 1 k = 4 SubClass Method1 SubClass Method2

补充:

子类重写父类的方法时候,不能抛出与父类方法不同的异常。意味着:如果父类的方法抛出了异常,子类重写该方法时没有抛出异常是合法的;但是如果父类中的方法没有抛出异常,而子类重写该方法时抛出了异常,那么就会编译错误;

另外,如果子类在重写父类的方法的时候抛出的异常与父类方法中抛出的异常不一样,那么也是会编译错误的,如父类方法中抛出的是InterruptedException,而子类重写该方法时抛出的是Exception,那么也会编译错误。

版权声明:转载需标明博客来源:http://blog.csdn.net/yangquanhui1991 大家互相学习,一起进步!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Albert陈凯

Scala之偏函数Partial Function

http://blog.csdn.net/bluishglc/article/details/50995939 从使用case语句构造匿名函数谈起 在Scal...

34790
来自专栏Kevin-ZhangCG

排序算法总结

20030
来自专栏Java编程

Java提高篇——详解内部类

可以将一个类的定义放在另一个类的定义内部,这就是内部类。

66200
来自专栏古时的风筝

Python----reduce原来是这样用的

官方解释: Apply function of two arguments cumulatively to the items of iterable, fro...

25860
来自专栏Java帮帮-微信公众号-技术文章全总结

Java基础-08(01)总结帮助文档,代码块,继承

? 1:如何制作帮助文档(了解) (1)写一个类 (2)加入文档注释 (3)通过javadoc工具生成即可 javadoc -d 目录 -author...

32450
来自专栏Hongten

java中子类的继承性

子类的成员中有一部分是子类自己申明定义的,另一部分是从他的父类继承的。子类继承父类的成员变量作为自己的一个成员变量,就好像他们是在子类中直接

16020
来自专栏我是业余自学C/C++的

纯虚函数

18720
来自专栏python学习指南

Scala入门学习笔记四--List使用

前言 本篇将介绍一个和Array很相似的集合List,更多内容请参考:Scala教程 本篇知识点概括 List的构造 List与Array的区别 Lis...

21270
来自专栏企鹅号快讯

Python网络爬虫之正则表达式

正则表达式非Python独有,在Python中通过re库模块实现。 ? 下面是一些常见的匹配模式 ? re.match re.match尝试从字符串的起始位置匹...

202100
来自专栏Python爱好者

Java基础笔记08

15650

扫码关注云+社区

领取腾讯云代金券