Java学习笔记Java 杂谈

Java--override 遇见 静态方法

2018-04-11  本文已影响8人  Ferrari1001

结论:

  【1】非静态方法属于类的实例,是可以被子类重写,从而达到多态效果;
  【2】静态方法属于类,是不能被重写的,子类中创建父类中同名的静态方法不会发生编译错误。
  【3】重写”只能适用于可观察的实例方法,不能用于静态方法和final、private关键字修饰的方法,对于静态方法,只能隐藏。

实例验证:

public class A {
    public void unstaticMethod() {
        System.out.println("SuperClass unstaticMethod");
    }

    public static void staticMethod() {
        System.out.println("SuperClass staticMethod");
    }
}

public class B extends A {
    public void unstaticMethod() {
        System.out.println("SunClass unstaticMethod");
    }

    public static void staticMethod() {
        System.out.println("SunClass staticMethod");
    }
}

public class Test {
    @SuppressWarnings("static-access")
    public static void main(String[] args) {
        A a1 = new A();
        A a2 = new B();
        a1.unstaticMethod();
        a2.unstaticMethod();
        a1.staticMethod();
        a2.staticMethod();
    }
}

#输出结果:
SuperClass unstaticMethod
SunClass unstaticMethod
SuperClass staticMethod
SuperClass staticMethod

剖析:

  在Java中我们静态方法的的选择是编译期就选择好的,是编译器自动根据声明类型帮我们选择的,它不依赖于任何对象。比如说static方法,可能有人会觉得这个static方法调用者是类对象啊,但我告诉你类对象是Class类型,也就是每个类的class静态域,比如String.class、ArrayList.class,他们并不包含我们要调用的目标静态方法,如下面代码所示:

public class NullInvoker {
    public static void testNullInvoker(){
        System.out.println("in testNullInvoker");
    }
    public static void main(String[] args) {
        NullInvoker NULL = null;//虽然这里是空指针,但是下面依然可以执行下去
        NULL.testNullInvoker();
    }
}

#输出结果:
in testNullInvoker

  所以说从语义就可以看出static、final、private方法本身都是编译期绑定的(也叫前期绑定)这些方法不存在多态,他们是在还没有运行的时候,程序在编译器里面就知道该调用哪个类的哪个方法了,而其他可观察的普通方法的绑定是在运行的时候根据具体的对象决定的,因为从语义上看这些方法是可被继承的,有了多态而造成了不确定性。

【注】关于java语言的静态重载和动态重写特性大家可以参考周志明著的《深入理解java 虚拟机》这本书。
上一篇 下一篇

猜你喜欢

热点阅读