16
public class Main
{
   public static void main(String []ar)
   {
      A m = new A();
      System.out.println(m.getNull().getValue());
   }
}

class A
{
   A getNull()
   {
      return null;
   }

   static int getValue()
   {
      return 1;
   }
}

我在一本 SCJP 书中遇到了这个问题。代码打印出来,1而不是预期的 NPE。有人可以解释一下原因吗?

4

5 回答 5

22

基本上,您调用的是静态方法,就好像它是实例方法一样。这只是解决了一个静态方法调用,所以就好像你写了:

A m = new A();
m.getNull();
System.out.println(A.getValue());

IMO,您的代码完全合法这一事实是 Java 的设计缺陷。它允许您编写非常具有误导性的代码,Thread.sleep例如我经常使用的示例:

Thread thread = new Thread(someRunnable);
thread.start();
thread.sleep(1000);

哪个线程进入睡眠状态?当前的,“当然”……

于 2012-04-10T11:43:03.800 回答
18

它的行为符合Java 语言规范

空引用可用于访问类(静态)变量而不会导致异常。

于 2012-04-10T11:45:49.447 回答
6

静态方法调用在编译时解析。编译器看到getNull()返回值的类型A是静态getValue()方法(并且没有同名的实例方法),因此在字节码中,实际返回值getNull()被忽略并被A.getValue()调用。

于 2012-04-10T11:45:40.103 回答
1

getNull 函数返回一个 A 对象。getValue 被声明为静态的,并且只需要 class_name 来运行,就像在 A.getValue() 中一样。因为 getNull 返回(实际上)一个 A 对象......你会得到 1

于 2012-04-10T11:46:36.417 回答
1

System.out.println(m.getNull().getValue()); 这行代码与 System.out.println(A.getValue());相同

因为getValue()方法是静态的,并且所有静态调用都在 java 的编译时启动因此,一旦您在非静态中创建getValue()就不会产生任何错误,这将产生错误,因为它将在运行时调用

于 2012-04-10T12:00:51.367 回答