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

看看下面的例子:

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

第一个println写入null但第二个抛出NullPointerException

为什么只有第二行值得一个例外? 那两个null之间有什么区别呢? Java中是否存在真正的 null虚假的 null

第一个调用将调用String.valueOf(Object)方法,因为您已经明确地将Object引用的types转换为null 。 相反,第二个将调用重载的String.valueOf(char[])方法,因为对于null参数, char[]Object更具体。

这个方法还有其他的重载版本可以接受原始参数,但是这些对于一个null参数来说并不是一个有效的匹配。

来自JLS§15.12.2 :

可能有不止一种这样的方法,在这种情况下,select最具体的方法。 最具体方法的描述符(签名加返回types)是在运行时用来执行方法调度的方法。

如果方法适用于子types(§15.12.2.2),适用于方法调用转换(§15.12.2.3),或者适用的variables方法(§15.12.2.4),则该方法适用。

[…]

如果在适用性testing的三个阶段中的一个阶段确定了几种适用的方法,则按照§15.12.2.5的规定select最具体的方法。

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

 // 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); } 

Java中有很多重载的String.valueOf方法。 此外,在Java中null有任何和所有types,以便任何东西(不是原语)都可以为null

所以,当你调用(String.valueOf((Object)null)你可以调用valueOf方法,该方法将一个Object使用显式的将nullObject

在第二个例子中,你并没有显式地将null成任何特定的types,所以实际上你可以用一个char[]来调用valueOf方法,这个方法会引发一个NPE。

从JLS§15.12.2

第二步search在上一步中确定的types的成员方法。 此步骤使用方法的名称和参数expression式的types来定位既可访问又适用的方法,即可以在给定参数上正确调用的声明。

可能有不止一种这样的方法,在这种情况下,select最具体的方法。 最具体方法的描述符(签名加返回types)是在运行时用来执行方法调度的方法。

在这种情况下, char[]Object 更具体 ,因此在没有明确强制转换null时调用它。

虽然我已经接受了一个答案,但是我想补充一个问题的确切答案,因为这两个答案集中在解释我陷入的陷阱。

(Object)nullnull之间的区别在于,第一个的types被强制为Object ,而第二个的types不是,因为我们可以认为它被强制为Object 。 相反,它也可以是一个数组而不是一个对象。

所以结论是:传递(Object)null而不是null作为一个方法的参数,以确保获得正确的方法工作的对象,而不是任何其他方法工作的数组。