结论先行: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()方法隐藏了,并未重写。

也就是说,静态方法不具有多态性,如果子类中静态方法的签名与父类中静态方法的签名相同,那么父类中的静态方法将被隐藏,而不是被重写

总结

  1. 静态方法不具有多态性。子类可以继承父类中的静态方法,但是不能重写父类中的静态方法。
  2. 子类中的实例方法不能隐藏父类中的静态方法,子类中的静态方法也不能隐藏父类中的实例方法。如果尝试用静态方法隐藏实例方法 或 用实例方法隐藏静态方法,则会在编译时报错
  3. 重写的前提
  1. 有继承关系,子类重新编写父类的方法(注意不重写属性)
  2. 子、父类中两个方法的方法名、参数列表必须相同方法体不同
  1. 重写注意事项
  • 子类中重写后方法的访问修饰符 不能小于 父类方法的访问修饰符(public > protected > default > private)
  • 子类方法的返回值以及抛出的异常小于等于 父类方法。比如:父类中throws IOException,子类中不能throws Exception,因为Exception > IOException
  • 若父类方法为private,则子类对其重写无效。