问题描述
根据文档,方法String.valueOf(Object obj)
返回:
如果参数为null
,则字符串等于"null"
;否则返回obj.toString()
的值.
但是为什么我尝试这样做:
System.out.println("String.valueOf(null) = " + String.valueOf(null));
它会抛出 NPE 吗?(不信自己试试!)
线程main"中的异常 java.lang.NullPointerException在 java.lang.String.(来源不明)在 java.lang.String.valueOf(Unknown Source)怎么会这样?文档在骗我吗?这是 Java 中的主要错误吗?
问题在于 String.valueOf
方法被重载:
Java 规范语言要求在这种情况下,选择最具体的重载:
JLS 15.12.2.5 选择最具体的方法
如果多个成员方法既可访问又适用于方法调用,则必须选择一个成员方法来为运行时方法分派提供描述符.Java 编程语言使用的规则是选择最具体的方法.
A char[]
is-an Object
,但不是所有的 Object
is-a char[]
.因此,char[]
比 Object
更具体,并且按照 Java 语言的规定,String.valueOf(char[])
在这种情况下选择了重载.
String.valueOf(char[])
期望数组为非null
,并且由于在这种情况下给出了null
,然后抛出 NullPointerException
.
简单的修复"是将 null
显式转换为 Object
,如下所示:
System.out.println(String.valueOf((Object) null));//打印空"
相关问题
故事的寓意
有几个重要的:
- Effective Java 2nd Edition,第 41 条:明智地使用重载
- 仅仅因为你可以超载,并不意味着你每次都应该
- 它们可能会引起混淆(尤其是当这些方法做的事情大不相同时)
- 使用好的 IDE,您可以检查在编译时选择了哪个重载
- 使用 Eclipse,您可以将鼠标悬停在上述表达式上,确实,选择了
valueOf(char[])
重载!
- 使用 Eclipse,您可以将鼠标悬停在上述表达式上,确实,选择了
- 有时您想显式地强制转换
null
(要遵循的示例)
另见
在铸造 null
至少有两种情况需要将 null
显式转换为特定的引用类型:
- 选择重载(如上例所示)
- 将
null
作为单个参数提供给可变参数
后者的一个简单例子如下:
static void vararg(Object... os) {System.out.println(os.length);}
然后,我们可以有以下内容:
vararg(null, null, null);//打印3"可变参数(空,空);//打印2"可变参数(空);//抛出空指针异常!vararg((Object) null);//打印1"
另见
- Java 语言指南/varargs -了解它是如何实施的
相关问题
according to the documentation, the method String.valueOf(Object obj)
returns:
But how come when I try do this:
System.out.println("String.valueOf(null) = " + String.valueOf(null));
it throws NPE instead? (try it yourself if you don't believe!)
Exception in thread "main" java.lang.NullPointerException at java.lang.String.(Unknown Source) at java.lang.String.valueOf(Unknown Source)
How come this is happening? Is the documentation lying to me? Is this a major bug in Java?
The issue is that String.valueOf
method is overloaded:
Java Specification Language mandates that in these kind of cases, the most specific overload is chosen:
JLS 15.12.2.5 Choosing the Most Specific Method
A char[]
is-an Object
, but not all Object
is-a char[]
. Therefore, char[]
is more specific than Object
, and as specified by the Java language, the String.valueOf(char[])
overload is chosen in this case.
String.valueOf(char[])
expects the array to be non-null
, and since null
is given in this case, it then throws NullPointerException
.
The easy "fix" is to cast the null
explicitly to Object
as follows:
System.out.println(String.valueOf((Object) null));
// prints "null"
Related questions
Moral of the story
There are several important ones:
- Effective Java 2nd Edition, Item 41: Use overloading judiciously
- Just because you can overload, doesn't mean you should every time
- They can cause confusion (especially if the methods do wildly different things)
- Using good IDE, you can check which overload is selected at compile time
- With Eclipse, you can mouse-hover on the above expression and see that indeed, the
valueOf(char[])
overload is selected!
- With Eclipse, you can mouse-hover on the above expression and see that indeed, the
- Sometimes you want to explicitly cast
null
(examples to follow)
See also
On casting null
There are at least two situations where explicitly casting null
to a specific reference type is necessary:
- To select overloading (as given in above example)
- To give
null
as a single argument to a vararg parameter
A simple example of the latter is the following:
static void vararg(Object... os) {
System.out.println(os.length);
}
Then, we can have the following:
vararg(null, null, null); // prints "3"
vararg(null, null); // prints "2"
vararg(null); // throws NullPointerException!
vararg((Object) null); // prints "1"
See also
- Java Language Guide/varargs - to understand how it's implemented
Related questions
这篇关于为什么 String.valueOf(null) 会抛出 NullPointerException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!