首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何理解Java中的隐藏与覆盖

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

作者头像
bear_fish
发布2018-09-20 11:26:09
3.1K0
发布2018-09-20 11:26:09
举报

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 大家互相学习,一起进步!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年11月07日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • java的重载、覆盖和隐藏的区别
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档