What is the difference between "(Object)null" and "null" in Java? [duplicate]
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
.
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?
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.
There are other overloaded versions of this method that accept primitive parameters, but those are not a valid match for a null
argument.
From 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).
[...]
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.
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);
}
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
.
So, when you call (String.valueOf((Object)null)
you call the valueOf
method that takes an Object
as use explicitly cast null
to 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.
From the 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.