12

我只是在和我的朋友讨论使用类名调用静态方法并尝试了这段代码,并希望它在运行时抛出 NPE。但事实证明它很有效。我只是想了解执行顺序。

public class One {

    public static void method() {
        System.out.println("in static one");
    }
}

public class Two {

    static One o;

    public static void main(String[] args) {
        o.method(); // expected NPE here, as o is null
    }
}

我知道应该使用它们的类名调用静态方法,我什至知道当我们使用实例调用静态方法时,IDE 会发出编译器警告。但是我们也可以通过创建实例来调用它们,但是,我从未在这里创建过实例,o应该将其默认值设为 null,因此调用o.method()应该在运行时抛出 NPE,但事实并非如此。你们能否解释一下这段代码中的执行顺序。

4

5 回答 5

7

它之所以有效,是因为重要的是该字段的编译时类型。o编译器将编译o.method()成与One.method().

特别是,如果你有一个Two扩展类One,并且都声明了一个static void method(),那么

One x = new Two();
x.method(); // calls One.method(), not Two.method()

有利于混淆目的,不太利于可维护性......

于 2012-12-06T21:13:13.713 回答
6

method是静态的,所以它不关心One实例。

One o = null;
o.method();

是相同的:

One.method();
于 2012-12-06T21:04:03.603 回答
0

static方法或变量与类定义本身相关联,而不与类实例相关联。因此,您method()在 上可用o,但理想情况下,您应该使用类名本身来调用它:

     One.method();//static way of calling static methods
于 2012-12-06T21:05:34.490 回答
0

因为您static One o;在函数外部声明main。您可以尝试在main函数内部声明它,甚至无法编译...

或者您可以将其声明为One o = nullin main,然后它将被编译但它与One.method()

于 2012-12-06T21:07:08.963 回答
0

如果您会在开发环境(例如 Eclipse)中打开代码,而不是通过在此处显示代码来愚弄人们,它确实为斜体样式的静态方法提供代码格式,那么您会看到 checkstyle 声称“不要在实例上调用静态方法”。

所以应该是

One.method()

代替

o.method()

那么它为什么不崩溃就很清楚了!

于 2012-12-06T21:10:34.073 回答