[英]Comparison of two null objects from two different types
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. 鉴于上面的例子,我们可以在某些方面承认输入了null
。 So why do the following lines print true
? 那么为什么以下行打印为true
? Sure o1
and o2
both have no value (ie null
), but they aren't from the same type ( Integer
vs Float
). 当然o1
和o2
都没有值(即null
),但它们不是同一类型( Integer
vs Float
)。 I firstly thought false
would have been printed. 我首先认为会打印false
。
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. 所有null
值都是无类型的并且是相等的。 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. 它不是键入的null
值,而是对可以键入的null的引用。
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. 编译器看到的类型a
作为A
所以静态方法被调用。 But the value referenced is null
and untyped. 但引用的值为null
且无类型。
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. 在不导致NullPointerException的情况下,您可以使用null
执行的唯一操作是分配或传递它而不检查它或将其与另一个引用进行比较。
BTW 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. 在运行时, null
被视为任何类型或没有类型,如果您尝试取消引用它,则会得到NullPointerException。
"==" in Java checks to see if it is the same instance rather than simply "are they equal?". Java中的“==”检查它是否是同一个实例,而不仅仅是“它们是否相等?”。 There is no concept of multiple instances of null in Java. Java中没有多个null实例的概念。 If you compare null to null, you will always receive true regardless of type. 如果将null与null进行比较,则无论何种类型,都将始终返回true。
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. 之所以你不能将null作为参数传递给与具有不同参数类型的另一个方法具有相同名称的方法,是因为任何一种方法都可以成为没有其他类型上下文的候选方法。 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 见http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.1
null
belongs to the "null type". null
属于“null类型”。 The "null type" has only one value - the null
. “null type”只有一个值 - null
。
The null type is a subtype of every reference type. null类型是每个引用类型的子类型。 Therefore we can do 因此我们可以做到
Integer i = null;
(Integer)null
In another word, null
is a valid value in every reference type. 换句话说, null
是每个引用类型中的有效值。
(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. 鉴于上面的例子,我们可以承认null不是类型的:当你调用m1(null)
,编译器无法确定实际参数的类型,也无法决定调用哪个方法。 All nulls are equal and not typed, and so (null==null)==true
. 所有空值都相等而不是类型,因此(null==null)==true
。
Null does not have a type, but a reference (to null
or anything else) has a type. Null没有类型,但引用 ( null
或其他任何内容)具有类型。 We can declare two reference variables with different types, but the null
they refer to is the same thing in both cases: 我们可以使用不同的类型声明两个引用变量,但它们引用的null
在两种情况下都是相同的:
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. 编译器使用它传递的引用类型来计算要调用的重载方法,而不是null
值本身的类型。
In your example it proves that the compiler cannot identity the type (of null) and decide which method to call. 在您的示例中,它证明编译器无法标识类型(null)并决定调用哪个方法。 So you have to explicity give the type. 所以你必须明确给出类型。 Also null == null
will be always true; null == null
也将始终为true; no matter whatever cast you do it doesnt change or give null a type. 无论你做什么演员,它都不会改变或给null一个类型。
This post has a long description on null
. 这篇文章对null
有很长的描述。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.