java变量和方法的覆盖和隐藏(翻译自Java Tutorials)
隐藏变量
在一个类里,如果一个变量的名字和父类的变量的名字一样,即使他们的类型不一样,那么在子类中,父类的同名变量无法直接通过变量名访问。
但是,父类的同名变量可以通过super访问。一般来说,不推荐隐藏变量,这样会让代码难以阅读
覆盖和隐藏方法
对象实例方法
在一个对象实例方法中,如果子类有一个方法,它的签名(方法名字,方法的参数个数和类型)和返回值都和父类一样,那么就是覆盖父类的方法。
子类覆盖的能力,允许一个类,继承父类的行为,根据需要修改某些行为。覆盖的方法,和父类对应的方法有一样的名字,一样的参数类型和个数,一样的返回类型。另一种覆盖方法可以返回父类的方法的返回类型的子类。这个称之为covariant返回类型。
当覆盖一个方法,你要使用注解@Override,告诉编译器你要覆盖父类的方法。但是,如果该方法不存在父类中,那么编译器会报错。
类方法
如果子类声明了一个与父类相同签名的类方法,子类隐藏了父类的方法。
隐藏和覆盖的区别具有很大的意义。覆盖方法的调用版本就是子类的方法。隐藏方法的调用版本,依赖于它是被父类调用,还是被子类调用。
下面有个例子,演示对象实例方法和类方法的区别,第一个类是Animal
public class Animal { public static void testClassMethod() { System.out.println("The class" + " method in Animal."); } public void testInstanceMethod() { System.out.println("The instance " + " method in Animal."); } }
第二个类是Cat,它是Animal的子类:
public class Cat extends Animal { public static void testClassMethod() { System.out.println("The class method" + " in Cat."); } public void testInstanceMethod() { System.out.println("The instance method" + " in Cat."); } public static void main(String[] args) { Cat myCat = new Cat(); Animal myAnimal = myCat; Animal.testClassMethod(); myAnimal.testInstanceMethod(); } }
Cat类覆盖了Animal的实例方法,并隐藏了它的类方法。结果输出如下:
The class method in Animal. The instance method in Cat.
和之前所说的一样,由于是通过父类调用隐藏方法,所以隐藏方法的调用版本是父类。而覆盖方法的调用版本是子类的方法。
修饰符
覆盖的访问修饰符可以允许扩大,但不允许缩小。例如,一个protected对象方法,可以在子类中修改为public,但不能是private。否则代码会在编译时出错。
方法覆盖和隐藏小结
下面的表格总结了在子类声明了一个与父类签名一样的方法的各种情况
Superclass Instance Method | Superclass Static Method | |
---|---|---|
Subclass Instance Method | Overrides | Generates a compile-time error |
Subclass Static Method | Generates a compile-time error | Hides |