静态方法的继承问题
最近看到静态方法的继承问题,看到网上的说法,自己还是有点不太理解,静态方法不是不可以被继承,同样的,静态方法也可以被继承,但是子类对于静态方法的“重写”是通过隐藏父类的静态方法来实现的,所以静态方法可以被继承,但是不能被重写,因此不能实现多态。
先看父类实例代码:
package test; public class StaticMethodExtendTestParent { public static void MethodA(){ System.out.println("Parent MethodA!"); } public void MethodB(){ System.out.println("Parent MethodB Call MethodA!"); MethodA(); } public void MethodC(){ System.out.println("Parent MethodC!"); } public void MethodD(){ System.out.println("Parent MethodD Call MethodC!"); MethodC(); } }
在子类中,“重写”了方法A和方法C:
package test; public class StaticMethodExtendTest extends StaticMethodExtendTestParent{ public static void MethodA(){ System.out.println("Child MethodA!"); } public void MethodC(){ System.out.println("Child MethodC!"); } }
基于以上的情况我们考虑多中情形:
(1)当我们直接用子类对象调用方法A和方法C
public static void main(String[] args) { StaticMethodExtendTest child = new StaticMethodExtendTest(); child.MethodA(); child.MethodC(); }
输出:
和我们平时的理解一样,调用的都是子类的A和C方法,这样看起来静态方法和非静态方法是一样的,好像都将父类的方法进行了重写覆盖。
(2)父类对象接受子类对象向上转型调用方法A和方法C
public static void main(String[] args) { StaticMethodExtendTestParent parent = new StaticMethodExtendTest(); parent.MethodA(); parent.MethodC(); }
输出:
这里我们看到方法C的输出很好的体现了java的多态性质,但是方法A仍然调用的是父类的方法A,这也就是我们前面说的,对于父类的静态方法,子类的“重写”只是将父类的方法隐藏。对于方法C,程序只有在程序运行时才能确定调用的到底是哪个类中实现的方法,有可能是基类的方法,有可能是基类的方法,这取决于StaticMethodExtendTestParent的实例对象接受的是哪一种类(StaticMethodExtendTestParent基类还是子类)。但是对于方法A,在实例对象的类型定义后就已经确定了,如果实例对象为StaticMethodExtendTestParent类型,那么无论对象实际接受的是哪一个子类的对象,方法A的调用始终是StaticMethodExtendTestParent的A方法。在上述实例中如果子类没有MethodA方法,那么子类对象对A方法的调用都将调用父类的A方法,所以静态方法可以被继承,但是不能被重写,无法实现多态。
(3)通过子类对象在父类的方法中调用被子类“重写”的方法
public static void main(String[] args) { StaticMethodExtendTest child = new StaticMethodExtendTest(); child.MethodA(); child.MethodB(); child.MethodC(); child.MethodD(); System.out.println("====================="); StaticMethodExtendTestParent parent = new StaticMethodExtendTest(); parent.MethodA(); parent.MethodB(); parent.MethodC(); parent.MethodD(); }
测试结果:
这里直接测试了两种情况,可以看出无论子类有没有向上转型,当调用父类方法时B,B中有对静态方法A的调用,都是直接调用的父类的静态方法A,方法D和C的调用则是我们熟知的多态的情形。