This question already has an answer here:
这个问题在这里已有答案:
- Why cast null to Object? 4 answers
- 为什么将null转换为Object? 4个答案
Take a look at the following example:
看一下下面的例子:
class nul
{
public static void main (String[] args)
{
System.out.println (String.valueOf((Object)null));
System.out.println (String.valueOf(null));
}
}
The first println
writes null
but the second throws a NullPointerException
.
第一个println写入null但第二个抛出NullPointerException。
Why is only the second line worth an exception? And what is the difference between the two null
s? Is there a real null
and a fake null
in Java?
为什么只有第二行值得例外?这两个空值有什么区别? Java中有真正的null和假的null吗?
3 个解决方案
#1
56
The first invocation will call the String.valueOf(Object)
method, as you have explicitly typecasted null
to Object
reference. Conversely, the second one will invoke the overloaded String.valueOf(char[])
method, as char[]
is more specific than Object
for a null
argument.
第一次调用将调用String.valueOf(Object)方法,因为您已明确地将null类型化为Object引用。相反,第二个将调用重载的String.valueOf(char [])方法,因为对于null参数,char []比Object更具体。
There are other overloaded versions of this method that accept primitive parameters, but those are not a valid match for a null
argument.
此方法的其他重载版本接受原始参数,但这些参数不是null参数的有效匹配。
From JLS §15.12.2:
来自JLS§15.12.2:
There may be more than one such method, in which case the most specific one is chosen. The descriptor (signature plus return type) of the most specific method is one used at run time to perform the method dispatch.
可能存在多于一种这样的方法,在这种情况下,选择最具体的方法。最具体方法的描述符(签名加返回类型)是在运行时用于执行方法分派的方法。
A method is applicable if it is either applicable by subtyping (§15.12.2.2), applicable by method invocation conversion (§15.12.2.3), or it is an applicable variable arity method (§15.12.2.4).
如果方法适用于子类型(第15.12.2.2节),适用于方法调用转换(第15.12.2.3节),或者它是适用的变量方法(第15.12.2.4节),则该方法适用。
[...]
[...]
If several applicable methods have been identified during one of the three phases of applicability testing, then the most specific one is chosen, as specified in section §15.12.2.5.
如果在适用性测试的三个阶段之一中确定了几种适用的方法,则选择最具体的方法,如第15.12.2.5节所述。
Now check the source code of both the methods:
现在检查两种方法的源代码:
// 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
16
There are lots of overloaded String.valueOf
methods in Java. Further, in Java null
has any and all types so that anything (that isn't a primitive) can be null
.
Java中有许多重载的String.valueOf方法。此外,在Java中,null具有任何和所有类型,因此任何(不是原始的)都可以为null。
So, when you call (String.valueOf((Object)null)
you call the valueOf
method that takes an Object
as use explicitly cast null
to Object
.
因此,当您调用(String.valueOf((Object)null)时,您调用valueOf方法,该方法将Object作为use使用显式地将null转换为Object。
In the second example you don't explicitly cast the null
to any particular type so in fact you call the valueOf
method with a char[]
which throws an NPE.
在第二个示例中,您没有显式地将null转换为任何特定类型,因此实际上您使用引发NPE的char []调用valueOf方法。
From the JLS §15.12.2
来自JLS§15.12.2
The second step searches the type determined in the previous step for member methods. This step uses the name of the method and the types of the argument expressions to locate methods that are both accessible and applicable, that is, declarations that can be correctly invoked on the given arguments.
第二步搜索上一步中为成员方法确定的类型。此步骤使用方法的名称和参数表达式的类型来定位可访问和适用的方法,即可以在给定参数上正确调用的声明。
There may be more than one such method, in which case the most specific one is chosen. The descriptor (signature plus return type) of the most specific method is one used at run time to perform the method dispatch.
可能存在多于一种这样的方法,在这种情况下,选择最具体的方法。最具体方法的描述符(签名加返回类型)是在运行时用于执行方法分派的方法。
In this case char[]
is more specific than Object
so it is called when no explicit cast of null
is made.
在这种情况下,char []比Object更具体,因此在没有进行显式的null转换时会调用它。
#3
6
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 (Object)null
and null
is that the type of the first is forced to Object
but the type of the second is not, as one could think, forced to Object
. Instead it could also be an array instead of an object.
(Object)null和null之间的区别在于第一个的类型被强制为Object,而第二个的类型并不像人们想象的那样被强制为Object。相反,它也可以是一个数组而不是一个对象。
So the conclusion is: pass (Object)null
instead of null
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)null而不是null作为方法的参数,以确保完全获得处理对象的方法而不是任何其他处理数组的方法。
#1
56
The first invocation will call the String.valueOf(Object)
method, as you have explicitly typecasted null
to Object
reference. Conversely, the second one will invoke the overloaded String.valueOf(char[])
method, as char[]
is more specific than Object
for a null
argument.
第一次调用将调用String.valueOf(Object)方法,因为您已明确地将null类型化为Object引用。相反,第二个将调用重载的String.valueOf(char [])方法,因为对于null参数,char []比Object更具体。
There are other overloaded versions of this method that accept primitive parameters, but those are not a valid match for a null
argument.
此方法的其他重载版本接受原始参数,但这些参数不是null参数的有效匹配。
From JLS §15.12.2:
来自JLS§15.12.2:
There may be more than one such method, in which case the most specific one is chosen. The descriptor (signature plus return type) of the most specific method is one used at run time to perform the method dispatch.
可能存在多于一种这样的方法,在这种情况下,选择最具体的方法。最具体方法的描述符(签名加返回类型)是在运行时用于执行方法分派的方法。
A method is applicable if it is either applicable by subtyping (§15.12.2.2), applicable by method invocation conversion (§15.12.2.3), or it is an applicable variable arity method (§15.12.2.4).
如果方法适用于子类型(第15.12.2.2节),适用于方法调用转换(第15.12.2.3节),或者它是适用的变量方法(第15.12.2.4节),则该方法适用。
[...]
[...]
If several applicable methods have been identified during one of the three phases of applicability testing, then the most specific one is chosen, as specified in section §15.12.2.5.
如果在适用性测试的三个阶段之一中确定了几种适用的方法,则选择最具体的方法,如第15.12.2.5节所述。
Now check the source code of both the methods:
现在检查两种方法的源代码:
// 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
16
There are lots of overloaded String.valueOf
methods in Java. Further, in Java null
has any and all types so that anything (that isn't a primitive) can be null
.
Java中有许多重载的String.valueOf方法。此外,在Java中,null具有任何和所有类型,因此任何(不是原始的)都可以为null。
So, when you call (String.valueOf((Object)null)
you call the valueOf
method that takes an Object
as use explicitly cast null
to Object
.
因此,当您调用(String.valueOf((Object)null)时,您调用valueOf方法,该方法将Object作为use使用显式地将null转换为Object。
In the second example you don't explicitly cast the null
to any particular type so in fact you call the valueOf
method with a char[]
which throws an NPE.
在第二个示例中,您没有显式地将null转换为任何特定类型,因此实际上您使用引发NPE的char []调用valueOf方法。
From the JLS §15.12.2
来自JLS§15.12.2
The second step searches the type determined in the previous step for member methods. This step uses the name of the method and the types of the argument expressions to locate methods that are both accessible and applicable, that is, declarations that can be correctly invoked on the given arguments.
第二步搜索上一步中为成员方法确定的类型。此步骤使用方法的名称和参数表达式的类型来定位可访问和适用的方法,即可以在给定参数上正确调用的声明。
There may be more than one such method, in which case the most specific one is chosen. The descriptor (signature plus return type) of the most specific method is one used at run time to perform the method dispatch.
可能存在多于一种这样的方法,在这种情况下,选择最具体的方法。最具体方法的描述符(签名加返回类型)是在运行时用于执行方法分派的方法。
In this case char[]
is more specific than Object
so it is called when no explicit cast of null
is made.
在这种情况下,char []比Object更具体,因此在没有进行显式的null转换时会调用它。
#3
6
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 (Object)null
and null
is that the type of the first is forced to Object
but the type of the second is not, as one could think, forced to Object
. Instead it could also be an array instead of an object.
(Object)null和null之间的区别在于第一个的类型被强制为Object,而第二个的类型并不像人们想象的那样被强制为Object。相反,它也可以是一个数组而不是一个对象。
So the conclusion is: pass (Object)null
instead of null
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)null而不是null作为方法的参数,以确保完全获得处理对象的方法而不是任何其他处理数组的方法。