简体   繁体   English

两种不同类型的两个空对象的比较

[英]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 ). 当然o1o2都没有值(即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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM