为什么这段代码没有抛出NullPointerException异常?

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,但实际上没有。你们能否解释一下这段代码的执行顺序呢?

1
字段o应该是static的。否则,您将无法从main访问它。 - reprogrammer
@reprogrammer 哈哈,是的,我编辑过了 :) - PermGenError
5个回答

7

这是因为关键的是o字段的编译时类型。编译器会将o.method()编译成与One.method()相同的字节码。

特别地,如果你有一个继承自One的类Two,并且两个类都声明了一个static void method(),那么

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

虽然可以用于混淆目的,但不利于可维护性...


太棒了,我现在明白了。我知道静态方法以及如何调用它们,但当它没有抛出NPE时我有些困惑。因此,在字节码中,即使我们使用实例调用静态方法,它仍将是One.method()。再次感谢Ian :) - PermGenError
@Ian - 如果我使用this.method()而不是o.method,为什么编译器不会将其编译成One.method() - Manoj
@Manoj,我认为编译器不会允许您在静态上下文中执行this.method() - Ian Roberts
1
@Manoj JLS §15.8.3 "关键字this只能在实例方法、实例初始化器或构造函数的主体中使用,或者在类的实例变量的初始化器中使用。如果它出现在其他任何地方,将会发生编译时错误。" - Ian Roberts

6

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

One o = null;
o.method();

与下面代码等效:

One.method();

0
如果您在开发环境中(例如Eclipse)打开代码,而不是在此处显示代码来提供静态方法的代码格式化为斜体样式,那么您会发现checkstyle声称“不要在实例上调用静态方法”。
因此应该是:
One.method()

替代

o.method()

那么现在就清楚为什么它不会崩溃了!


你可能需要先阅读完整的问题。我知道如何调用静态方法。我的疑问是当 o 为 null 时为什么它不会抛出 NPE。但是,我从 Ian 那里得到了答案,并使用字节码轮廓检查了代码。它基本上将所有对静态方法的调用转换为类名.方法名。 - PermGenError

0

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

     One.method();//static way of calling static methods

如问题所述,我知道它们应该使用classname.methodname()进行调用,但我的问题是为什么它不会抛出NPE?你能给出原因吗? - PermGenError
@GanGnaMStYleOverFlowErroR:我用粗体回答了。静态方法或变量与类定义本身相关联,它们不需要类实例。 - Yogendra Singh

0

因为你在main函数之外声明了static One o;,所以如果你尝试在main函数中声明它,则无法编译...

或者你可以在main中声明为One o = null,这样它将被编译,但这与One.method()相同。


这没有任何意义,如果我在 main 函数外声明一个变量又有什么用呢? - PermGenError
@GanGnaMStYleOverFlowErroR 这将会出现 java.lang.Error: 未解决的编译问题 - bhuang3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接