我们在子类重写父类的静态方法在编译过程是不会报错的,但是却达不到预期的效果。
也就是说,重写静态方法,java不会阻止你这么做, 但是你却得不到预期的结果(父类的引用指向子类对象的时候,调用的仍然是父类的静态方法)。
下面我们来写几个方法看一下结果:
class SuperClass{
//......
//父类静态方法
public static void staticMethod(){
System.out.println("SuperClass: inside staticMethod");
}
//......
}
public class SubClass extends SuperClass{
//......
//重写父类静态方法
public static void staticMethod(){
System.out.println("SubClass: inside staticMethod");
}
//......
public static void main(String []args){
//......
//父类引用指向父类对象
SuperClass superClassWithSuperCons = new SuperClass();
//父类引用指向父类对象(多态)
SuperClass superClassWithSubCons = new SubClass();
//子类引用指向子类对象
SubClass subClassWithSubCons = new SubClass();
superClassWithSuperCons.staticMethod();
superClassWithSubCons.staticMethod();
subClassWithSubCons.staticMethod();
//......
}
}
运行结果:
SuperClass: inside staticMethod
SuperClass: inside staticMethod
SubClass: inside staticMethod
我们预期的superClassWithSubCons(第二个) 输出的应该是子类的静态方法,然而却输出了父类的静态方法。
为什么静态方法这么特殊呢?
原因是因为静态方法是属于类的方法,他在编译期就已经存储在了方法区,当我们使用父类引用调用子类静态方法时,会直接在方法区去找这个方法,找到的当然是属于父类的静态方法。
静态方法是在编译阶段使用了编译类型信息,进行静态绑定的。
而普通方法使用父类引用调用子类方法时,我们java栈里面找到引用,然后在堆里面找到了子类的对象,那么调用的是子类的方法。
所以:使用对象引用来访问静态方法仅仅是Java设计者给程序猿的自由。我们应该直接使用类名来访问静态方法,而不要使用对象引用来访问。
人生最重要的结局是:
我们终有一天,要学会和自己平凡不完美的父母达成和解。
我们终有一天,要学会和自己、和这个世界达成和解。
无论它在你看来美丽,或丑陋。
——北野武