本文介绍了为什么 String.valueOf(null) 会抛出 NullPointerException?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据文档,方法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[]) 重载!
  • 有时您想显式地强制转换 null(要遵循的示例)

另见

在铸造 null

至少有两种情况需要将 null 显式转换为特定的引用类型:

  • 选择重载(如上例所示)
  • null 作为单个参数提供给可变参数

后者的一个简单例子如下:

static void vararg(Object... os) {System.out.println(os.length);}

然后,我们可以有以下内容:

vararg(null, null, null);//打印3"可变参数(空,空);//打印2"可变参数(空);//抛出空指针异常!vararg((Object) null);//打印1"

另见

相关问题

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!
  • 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

Related questions

这篇关于为什么 String.valueOf(null) 会抛出 NullPointerException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-02 01:22