Java 为什么';这段代码不会抛出NullPointerException吗

Java 为什么';这段代码不会抛出NullPointerException吗,java,static,classloader,static-methods,Java,Static,Classloader,Static Methods,我刚刚和我的朋友讨论了如何使用类名调用静态方法,并尝试了这段代码,希望它在运行时抛出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) {

我刚刚和我的朋友讨论了如何使用类名调用静态方法,并尝试了这段代码,希望它在运行时抛出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,但它没有。你们能解释一下这段代码的执行顺序吗

方法
是静态的,因此它不关心
一个
实例

One o = null;
o.method();
同:

One.method();

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

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

因为你声明了
静态的一个o
主功能之外。您可以尝试在
main
函数中声明它,它甚至无法编译


或者您可以在
main
中将其声明为
One o=null
,然后它将被编译,但如果您要在开发环境(例如Eclipse)中打开代码,则它与
One.method()相同,
这里显示的代码确实以斜体样式为静态方法提供了代码格式化,而不是愚弄人们,那么您将看到checkstyle声称“不要在实例上调用静态方法”

应该如此

One.method()
而不是

o.method()

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

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

特别是,如果有一个类
Two
扩展了
One
,并且都声明了一个
静态void方法()
,那么

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

适用于模糊处理,不适用于可维护性…

字段
o
应为
静态
。否则,您将无法从
main
@reprogrammer Haah,是的,编辑了它:)访问它没有任何意义,所以如果我在main之外声明一个???@gangnamstyleoverflowerr,它将具有
java.lang。错误:未解决的编译问题,如问题中所述,我知道应该用classname.methodname()调用它们,但我的问题是为什么它不抛出NPE??你能说出原因吗?@GangnamStyleOverflower错误:我用粗体回答<代码>静态方法或变量与类定义本身相关联
,它们不需要类实例。太棒了,我现在知道了,我对静态方法和如何调用它们很陌生,但只是在它抛出NPE时感到困惑。所以基本上在字节码中,它应该是1.method(),即使我们用instace调用static方法。。再次感谢ian:)@ian-如果是使用
this.method()
而不是
o.method
为什么编译器不把它编译成
One.method()
?@Manoj我认为编译器不允许你在静态上下文中执行
这个.method()
。@Manoj关键字
this
只能在实例方法、实例初始值设定项或构造函数的主体中,或在类的实例变量的初始值设定项中使用。如果它出现在其他地方,则会发生编译时错误。“您可能需要先阅读我的完整问题。我知道如何调用静态方法。我的疑问是,当o为空时,它为什么不抛出NPE。我从伊恩那里得到了答案,并用字节码大纲检查了代码。它基本上将所有对静态方法的调用转换为类名。方法名。