public void m1(Integer f) {
...
}
public void m1(Float f) {
...
}
public void main() {
m1(null); // error: the method m1(Integer) is ambiguous for the type Main
m1((Integer) null); // success
}
Given the above example, we can admit in some ways that null
is typed. So why do the following lines print true
? Sure o1
and o2
both have no value (ie null
), but they aren't from the same type ( Integer
vs Float
). I firstly thought false
would have been printed.
Integer i = null;
Object o1 = (Object) i;
Float f = null;
Object o2 = (Object) f;
System.out.println(o1 == o2); // prints true
// in short:
System.out.println(((Object) ((Integer) null)) == ((Object) ((Float) null))); // prints true
All null
values are untyped and are equal. You can pass it to different reference types but it makes no difference for comparison purposes.
It is not the null
value which is typed but the reference to the null which can be typed.
A common question is what happens here
class A {
public static void hello() { System.out.println("Hello World"); }
public static void main(String... args) {
A a = null;
a.hello();
System.out.println("a is an A is " + (a instanceof A)); // prints false.
}
}
The compiler sees the type of a
as an A
so the static method is called. But the value referenced is null
and untyped.
The only operations you can perform with null
without causing a NullPointerException is to assign or pass it without examining it or comparing it with another reference.
BTW
In short: The compiler will select a method based on the type of the reference, at runtime the execution is based on the class of the object referenced. At runtime null
is treated as any type or no type or you get a NullPointerException if you try to dereference it.
"==" in Java checks to see if it is the same instance rather than simply "are they equal?". There is no concept of multiple instances of null in Java. If you compare null to null, you will always receive true regardless of type.
The reason why you cannot then pass null as an argument to a method with the same name as another with different parameter types is because either method could be a candidate to be called without further type context. Rather than guess which one that might be, it correctly indicates an error.
see http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.1
null
belongs to the "null type". The "null type" has only one value - the null
.
The null type is a subtype of every reference type. Therefore we can do
Integer i = null;
(Integer)null
In another word, null
is a valid value in every reference type.
(Think of a type as a set of values; the types of a value is the sets it belongs to; "subtype" means "subset". )
Given the above example, we can admit that null is NOT typed: when you call m1(null)
, compiler cannot determine the type of the actual parameter and cannot decide which method to invoke. All nulls are equal and not typed, and so (null==null)==true
.
Null does not have a type, but a reference (to null
or anything else) has a type. We can declare two reference variables with different types, but the null
they refer to is the same thing in both cases:
Integer a = null;
Double b = null;
In your example,
m1((Integer) null);
the compiler uses the type of the reference it is passed to work out which overloaded method to call, not the type of the null
value itself.
In your example it proves that the compiler cannot identity the type (of null) and decide which method to call. So you have to explicity give the type. Also null == null
will be always true; no matter whatever cast you do it doesnt change or give null a type.
This post has a long description on null
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.