------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
隐藏(hide):子类的某个字段、静态方法、成员内部类与其父类的具有相同名字(对于静态方法还需要相同的参数列表),此时父类对应的字段、静态方法、成员内部类就被隐藏了。
举个例子,天鹅(Swan)是会飞的,而丑小鸭(UglyDuck)小时候是不会飞的,看看下面的代码,看看能够打印出什么。
- class Swan {
- public static void fly() {
- System.out.println("swan can fly ...");
- }
- }
- class UglyDuck extends Swan {
- public static void fly() {
- System.out.println("ugly duck can‘t fly ...");
- }
- }
- public class TestFly {
- public static void main(String [] args) {
- Swan swan = new Swan();
- Swan uglyDuck = new UglyDuck();
- swan.fly();
- uglyDuck.fly();
- }
- }
按道理的话,我们认为应该是输出两句不同的结果,因为我们可能认为 UglyDuck 继承了 Swan 并且“重写”了 fly() 方法,而且在 main() 方法中 Swan uglyDuck = new UglyDuck(); 也表明了 uglyduck 实际上是 UglyDuck 类型的,因此构成了多态行为。
其实,运行结果是两句“swan can fly ...”,为什么会这样子?原因有下:
1、父类 Swan 中的 static 静态方法 fly() 是不能被重写的,上一段我对重写二字用了双引号;
2、尽管子类 UglyDuck 中的 fly() 方法与父类中的有一致的参数列表,但是对于 static 方法来说,这叫隐藏(hide),而不是重写(override);
3、对于 static 方法,根本不存在像多态那样的动态分派机制,JVM 不会根据对象引用的实际类型来调用对应的重写方法。这一点在个例子中是最重要的。
对于 static 方法,我们称之为类方法,不是实例方法,对 static 方法的调用直接用所属类名加个点就行,如 UglyDuck.fly() 。而实例方法就不得不使用对象引用来获得其可访问方法的调用权。在上面的例子 main() 中的 uglyDuck.fly() 语句,JVM 根本据不会去判断 uglyDuck 引用的究竟是什么类型,既然调用的是 fly() 方法,那么 JVM 只会根据 uglyDuck 的声明类型(即 Swan 类)去获得该 static 方法的调用。根本就谈不上多态…
这就说明,最好避免用对象引用的方式来访问一个 static 方法。此外,别以为在继承关系上的父类、子类只要方法名、参数列表一致就是重写(override)而构成多态,其实还得看看父类中的方法有没有被什么修饰符声明(在这个例子中是 static 修饰的)。再如 final 修饰符的方法则表明不可被子类重写,即方法名、参数列表不能和父类完全一致。在我看来,这一类修饰符就表明了方法、变量、字段等特有的性质,或者是身份。