Java中的“(Object)null”和“null”有什么区别?

2022-08-31 20:15:52

请看以下示例:

class nul
{
  public static void main (String[] args)
  {
    System.out.println (String.valueOf((Object)null));
    System.out.println (String.valueOf(null));
  }
}

第一个写入,但第二个抛出 .printlnnullNullPointerException

为什么只有第二行值得例外?这两个s有什么区别?Java中有吗?nullnullnull


答案 1

第一个调用将调用 String.valueOf(Object) 方法,因为您已经显式地将类型转换为引用。相反,第二个将调用重载的 String.valueOf(char[]) 方法,因为它比参数更具体。nullObjectchar[]Objectnull

此方法还有其他接受基元参数的重载版本,但这些版本不是参数的有效匹配项。null

来自 JLS §15.12.2

可能有多个这样的方法,在这种情况下,选择最具体的方法。最具体方法的描述符(签名加返回类型)是在运行时用于执行方法调度的描述符。

如果方法可通过子类型化 (§15.12.2.2)、通过方法调用转换(§15.12.2.3)适用,或者该方法可通过变量 arity 方法 (§15.12.2.4) 适用,则该方法适用。

[...]

如果在适用性测试的三个阶段之一中确定了几种适用的方法,则选择最具体的方法,如§15.12.2.5节所述。

现在检查这两种方法的源代码:

// This won't throw NPE for `obj == null`
public static String valueOf(Object obj) {
    return (obj == null) ? "null" : obj.toString();
}

// This will throw `NPE` for `data == null`
public static String valueOf(char data[]) {
    return new String(data);
}

答案 2

Java中有很多重载的方法。此外,在Java中具有任何和所有类型,因此任何内容(不是基元)都可以是。String.valueOfnullnull

因此,当您调用时,您调用的方法将 as use 显式转换为 。(String.valueOf((Object)null)valueOfObjectnullObject

在第二个示例中,您没有显式地将 强制转换为任何特定类型,因此实际上您使用 a 调用该方法,这会引发 NPE。nullvalueOfchar[]

来自 JLS §15.12.2

第二步搜索上一步中确定的类型,以查找成员方法。此步骤使用方法的名称和参数表达式的类型来查找可访问且适用的方法,即可以在给定参数上正确调用的声明。

可能有多个这样的方法,在这种情况下,选择最具体的方法。最具体方法的描述符(签名加返回类型)是在运行时用于执行方法调度的描述符。

在这种情况下,它比这样更具体,因此在没有显式强制转换时调用它。char[]Objectnull