Java 重载、重写和隐藏的区别

Java 重载、重写和隐藏的区别

 

 

一、重载(Overload)

注意:为了正确的区分重载和重写,请各位务必记清重载(Overload)和重写(Override)的英文。

1)重载定义:表示两个或多个方法的名字相同,但方法的参数不同。方法参数不同有两层含义:A、参数的个数不同;B、参数的类型不同。

[java] view plain copy

  1. public void run(String name, int count)  
  2. {  
  3. System.out.println(count + " " + name + " " + "are running.");  
  4. }  
  5. public void run(int count, String name)  
  6. {  
  7. System.out.println(count + " " + name + " " + "are running.");  
  8. }  

请思考以上两个方法是否构成了重载?

2)重载发生的时机:重载是发生在同一个类内部的两个或多个方法之间。

3)方法的返回类型对重载没有任何影响!即,对于方法名字和参数都相同的两个方法,如果他们的返回类型不同,这种语法格式是错误的,大家可以试一试。那么,也就是说,只要是重载返回类型一定相同。否则为两个不同的方法。如下代码,这是两个不同的方法。

[java] view plain copy

  1. public void run()  
  2. {  
  3. System.out.println("dog is running");  
  4. }  
  5. public int run(String name, int count)  
  6. {  
  7. System.out.println(count + " " + name + " " + "are running.");  
  8. return 1;  
  9. }  

3)构造方法之间的重载:一个类中有多个构造方法,那么它们一定是重载的。

4)重载方法之间的调用:对于普通方法的重载,重载的方法之间是可以直接调用的,如下代码一。

但是对于重载的构造方法之间的调用,需要使用this()关键字。A、this()括号中参数表示目标构造方法所接收的参数;B、对this()的调用必须是构造方法的第一条语句。如下代码二。

[java] view plain copy

  1. public int run(String name, int count)  
  2. {  
  3. System.out.println(count + " " + name + " " + "are running.");  
  4. return 1;  
  5. }  
  6. public void run(int count, String name)  
  7. {  
  8. run(name , count);  
  9. System.out.println(count + " " + name + " " + "are running.");  
  10. }  

[java] view plain copy

  1. public Dog()  
  2. {  
  3. this("金巴");  
  4. System.out.println("你好世界,我是一条狗!");  
  5. }  
  6. public Dog(String name)  
  7. {  
  8. System.out.println("你好世界," + "我是一条" + name + "狗!");  
  9. }  

 

 

二、重写(Override)

1)重写定义:子类与父类的方法的返回类型一样,方法名称一样,参数一样,这样我们就说子类与父类的方法构成了重写关系。

 补充:在重写中,我们一直没提到权限的问题(public、protected、private),使用private修饰的方法是不能够进行重写的,也不能够被继承,所以private和多态扯不上关系。在同一个包下,构成重写关系,父类和子类的方法,权限可以是public和public、protected和protected、protected和public,但不可能是public和protected,即权限可以扩大但不可缩小。

2)重写发生的时机:重写发生在父类与子类之间。

3)构造方法时不能重写的,如果您理解是构造方法的作用,就知道构造方法为什么不能重写。

4)在重写时,子类重写的方法调用父类被重写的方法时,可以使用super.父类方法的方式调用,其中此语句不必放在第一行。如下代码所示:

[java] view plain copy

[java] view plain copy

  1. class Animal  
  2. {  
  3. public void run()  
  4. {  
  5. System.out.println("animal is running");  
  6. }  
  7. }  
  8. class Dog extends Animal  
  9. {  
  10. //override  
  11. public void run()  
  12. {  
  13. System.out.println("dog is running");  
  14. super.run();  
  15. }  
  16. }  

 

 

三、隐藏(Hide)
1)提到隐藏,就不得不提到一个关键字--static,static是静态的意思,具体用法意义,各位可以去查相关的资料。这里我想说的,static方法在继承中的特殊性!
1)子类不能重写(Overriding)父类的静态方法,只能隐藏(Hiding)父类的静态方法。

2)什么叫隐藏父类的静态方法呢?就是说父类的静态方法和子类的静态方法是同时存在的,具体调用的是哪个方法,是要看调用的方法的引用是什么类型的引用,如果是父类型的引用,调用的就是父类的静态方法,如果是子类型的引用,调用的就是子类的静态方法。【这里面有些多态(Polymorphism)的知识,不懂的可以问我哈!】具体区别我们可以看一个例子,这个例子来自官方文档。

[java] view plain copy

  1. public class Animal   
  2. {  
  3. public static void testClassMethod()   
  4. {  
  5. System.out.println("The class" + " method in Animal.");  
  6. }  
  7. public void testInstanceMethod()   
  8. {  
  9. System.out.println("The instance " + " method in Animal.");  
  10. }  
  11. }  

The second class, a subclass of Animal, is called Cat:

[java] view plain copy

  1. public class Cat extends Animal   
  2. {  
  3. public static void testClassMethod()   
  4. {  
  5. System.out.println("The class method" + " in Cat.");  
  6. }  
  7. public void testInstanceMethod()  
  8. {  
  9. System.out.println("The instance method" + " in Cat.");  
  10. }  
  11. public static void main(String[] args)   
  12. {  
  13. Cat myCat = new Cat();  
  14. Animal myAnimal = myCat;  
  15. Animal.testClassMethod();  
  16. myAnimal.testInstanceMethod();  
  17. }  
  18. }  

 

 

 

 

 

 

 

 

 

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

 

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

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

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

 

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

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

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

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

隐藏和覆盖的区别:

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

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

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

 

特殊情况:

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

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

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

  4.private 方法隐式添加了final

实例:

SuperClass类:

   package com.yilong.test.scjp;  

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

 

posted @ 2017-10-10 17:43  SinglePark  阅读(1214)  评论(0编辑  收藏  举报