8

查看与此问题类似的示例代码:

public class A {
    public static void main(String args[]){
        A a = new A();
        System.out.println(a.equals((a = null)));
    }
}

这打印错误。为什么它不会因 NullPointerException 而失败?必须在 equals 方法运行之前处理分配,但是在评估整行之前,这不会影响调用 equals 的引用吗?

我没有看到它在 Java 语言规范中的哪个地方描述了这一点,我是否在某个地方错过了它?

4

2 回答 2

9

来自JLS

在运行时,方法调用需要五个步骤。首先,可以计算目标参考。其次,评估参数表达式。第三,检查要调用的方法的可访问性。第四,定位要执行的方法的实际代码。第五,创建新的激活帧,必要时进行同步,并将控制转移到方法代码。

这表明在a.equals((a = null)). 发生以下步骤:

  1. a的参考被计算。这有时称为“绑定方法调用”。
  2. a=null作为评估参数的一部分进行评估。它不影响步骤 1。
  3. 的可访问性equals(Object)已检查。
  4. JVM 内部代码查找实际的字节码。
  5. 调用发生

显然,之前a确定的引用被清空,避免了 NPE。 a

于 2014-05-23T18:20:09.407 回答
2

我相信您感兴趣的 JLS 部分是

15.12.4。方法调用的运行时评估

在运行时,方法调用需要五个步骤。首先,可以计算目标参考。其次,评估参数表达式

因此,目标的评估发生时a仍然有一个非空值,然后a设置null为方法调用的参数。this因此,使用对以前称为 的对象的引用来调用 equals 方法,该对象a仍然存在,并带有一个空参数。

于 2014-05-23T18:21:59.250 回答