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

What is the difference between "(Object)null" and "null" in Java? [duplicate]

提问人:ceving 提问时间:10/11/2013 最后编辑:Rohit Jainceving 更新时间:8/23/2016 访问量:3118

问:

请看以下示例:

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

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

为什么只有第二行值得例外?两者之间有什么区别?Java 中有之分吗?nullnullnull

java null nullpointerexception

评论

1赞 bmargulies 10/11/2013
如果你看一下 String 的 Javadoc,答案就是在 valueOf 的两个相关重载中盯着你。
0赞 tckmn 10/12/2013
高度相关:stackoverflow.com/questions/3131865/...

答:

56赞 Rohit Jain 10/11/2013 #1

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

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

来自 JLS §15.12.2

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

如果某个方法通过子类型适用,则该方法适用 (§15.12.2.2),适用于方法调用转换 (§15.12.2.3), 或者它是一种适用的可变方法 (§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);
}

评论

6赞 Petr Janeček 10/11/2013
(因为编译器将作为参数调用的方法解析为它能找到的最具体的方法。并且比 .) 更具体。nullchar[]Object
1赞 ceving 10/11/2013
所以这是一个 Java 错误,因为 的两种实现不一样。Object 实现认为 null 应该打印为 null,但 char 数组实现认为 null 应该导致异常。同样的方法对什么是例外有不同的思考。valueOf
5赞 Boris the Spider 10/11/2013
@ceving java 错误?不,绝对不是!应打印为 .并且 a 不能转换为 a,因此会抛出异常。它们是不同的方法,这就是重点。错误到底在哪里?Objectnullnullchar[]String
1赞 Rohit Jain 10/11/2013
@htor方法和方法。嗯,不,没有任何标准。.static#instance
2赞 ceving 10/11/2013
@BoristheSpider 如果他们有不同的名字,我会同意你的看法。但它们具有相同的名称,因此不是不同的方法。
16赞 Boris the Spider 10/11/2013 #2

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

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

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

摘自 JLS §15.12.2

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

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

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

评论

0赞 sactiw 6/19/2015
因此,底线是避免将 raw 作为参数传递给方法,而是将它们转换为该方法的 param 类型。:)null
6赞 ceving 10/11/2013 #3

Although I accepted already an answer I would like to add the exact answer to the question, because the two answers concentrate on explaining the trap I walked into.

The difference between and is that the type of the first is forced to but the type of the second is not, as one could think, forced to . Instead it could also be an array instead of an object.(Object)nullnullObjectObject

So the conclusion is: pass instead of as an argument to a method to be sure to get exactly the method working on objects instead of any other method working on arrays.(Object)nullnull

评论

0赞 Sebastiaan van den Broek 10/12/2013
Well yes, as Rohit already mentioned, a method call will always be matched to the method with the most specific subtype.