结论先行:static方法不能被重写!
实践验证
在下面的两个例子中,我们定义两个类A和B,A是B的子类,分别给出test()为静态方法和非静态方法时的运行结果。
例1:test()为static方法
public class Main {
public static void main(String[] args) {
A a = new A();
a.test();// 输出 A=>test()
B b = new A();
b.test();// 输出 B=>test(),说明父类中的test()方法没有被重写
}
}
// 父类
class B {
public static void test(){
System.out.println("B=>test()");
}
}
// 子类
class A extends B {
public static void test(){
System.out.println("A=>test()");
}
}
运行结果:父类中的test()方法没有被重写!
A=>test()
B=>test()
例2:test()为非static方法
public class Main {
public static void main(String[] args) {
A a = new A();
a.test();// 输出 A=>test()
B b = new A();
b.test();// 输出 A=>test(),说明父类中的test()方法被重写了
}
}
// 父类
class B {
public void test(){
System.out.println("B=>test()");
}
}
// 子类
class A extends B {
public void test(){
System.out.println("A=>test()");
}
}
运行结果:父类中的test()方法被重写了!
A=>test()
A=>test()
结果分析
在Java中,如果子类和父类中各有一个static方法,且它们的返回值类型、方法名、参数列表都相同(具有相同的签名),那么这两个static方法并不具有重写关系。
B b = new A()
可以理解为父类(B)的引用(b)指向了子类(A)的对象,即b指向new A()
。这是子类类型转父类类型,属于向上转型,在这个过程中,子类中的test()方法只是将父类中的test()方法隐藏了,并未重写。
也就是说,静态方法不具有多态性,如果子类中静态方法的签名与父类中静态方法的签名相同,那么父类中的静态方法将被隐藏,而不是被重写。
总结
- 静态方法不具有多态性。子类可以继承父类中的静态方法,但是不能重写父类中的静态方法。
- 子类中的实例方法不能隐藏父类中的静态方法,子类中的静态方法也不能隐藏父类中的实例方法。如果尝试用静态方法隐藏实例方法 或 用实例方法隐藏静态方法,则会在编译时报错。
- 重写的前提:
- 有继承关系,子类重新编写父类的方法(注意不重写属性)
- 子、父类中两个方法的方法名、参数列表必须相同,方法体不同。
- 重写注意事项:
- 子类中重写后方法的访问修饰符 不能小于 父类方法的访问修饰符(public > protected > default > private)
- 子类方法的返回值以及抛出的异常要 小于等于 父类方法。比如:父类中throws IOException,子类中不能throws Exception,因为Exception > IOException
- 若父类方法为private,则子类对其重写无效。