【问题标题】:why doesn't this code throw NullPointerException为什么这段代码不抛出 NullPointerException
【发布时间】:2012-11-25 00:07:31
【问题描述】:

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

【问题讨论】:

  • 字段o 应该是static。否则,您将无法从main 访问它。
  • @reprogrammer 哈哈,是的,编辑了它:)

标签: java static classloader static-methods


【解决方案1】:

之所以有效,是因为重要的是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() e即使我们用实例调用静态方法..再次感谢 ian :)
  • @Ian - 如果是使用this.method() 而不是o.method 为什么编译器不把它编译成One.method()
  • @Manoj 我认为编译器不允许你在静态上下文中执行this.method()
  • @Manoj JLS §15.8.3 "关键字this只能用在实例方法、实例初始化器或构造器的主体中,或者在类的实例变量的初始化器中。如果它出现在其他任何地方,都会发生编译时错误。”
【解决方案2】:

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

应该是这样的

One.method()

而不是

o.method()

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

【讨论】:

  • 您可能需要先阅读我的完整问题。我知道如何调用静态方法。我的疑问是为什么当 o 为 null 时它不抛出 NPE。我从伊恩那里得到答案并使用字节码大纲检查了代码的任何人。它基本上将所有对静态方法的调用转换为类名。方法名称。
【解决方案3】:

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

或者你可以在main中声明为One o = null,那么它会被编译但是和One.method()一样

【讨论】:

  • 没有任何意义,那么如果我在 main 之外声明一个呢??
  • @GanGnaMStYleOverFlowErroR 会有java.lang.Error: Unresolved compilation problem
【解决方案4】:

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

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

【讨论】:

  • 如问题中所述,我知道应该使用 classname.methodname() 调用它们,但我的问题是它为什么不抛出 NPE ?你能说出原因吗??
  • @GanGnaMStYleOverFlowErroR:我用粗体回答。 static methods or variables are associated with class definition itself 并且它们不需要类实例。
【解决方案5】:

method 是静态的,因此它不关心 One 实例。

One o = null;
o.method();

等同于:

One.method();

【讨论】:

    猜你喜欢
    • 2013-11-13
    • 1970-01-01
    • 1970-01-01
    • 2013-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多