为什么可以在 Java 中通过引用比较不兼容的类型?

Why is it possible to compare incompatible types by reference in Java?

看看这个片段:

    List<Integer> c = new ArrayList<>();
    Map<String,Boolean> m = new HashMap<>();
    if( c == m ) //no error here!  WHY?
    {
        c = m; //"Incompatible types" error, as expected.
        m = c; //"Incompatible types" error, as expected.
    }

为什么c == m没有报错?

我正在使用 jdk1.8.0.20 的 javac,我没有理由怀疑它无视 java 语言规范,所以这是相当绝对的确定性在规范中,所以:

规范允许这样的东西有什么意义/目的/用处?

出现Incompatible types错误是因为当赋值被触发时,一个名为Assignment conversion的操作开始了。它的作用是:

Assignment conversion occurs when the value of an expression is assigned (§15.26) to a variable: the type of the expression must be converted to the type of the variable.

如果转换失败,则会抛出编译时错误。

但是,当 == operator 发生时,不会抛出编译时错误。

写的时候

if(c==m)

你只是在检查@hashcode 在某些情况下两个对象可能相同,所以你可能不会在该行中收到任何错误!

仅仅因为类型不可转换并不意味着它们不是相等的对象。如果类型是 "Inconvertible",则意味着需要强制转换来检查类型实际上是否可转换。

interface Outputer extends Consumer<String>, Serializable { }

Outputer out = System.out::println;
Consumer<String> cs = out;
Serializable s = out;
System.out.println(s == cs); // prints true

// s = cs; // Inconvertible types, doesn't compile
s = (Serializable) cs; // compiles and runs fine.

css 是不可转换的类型,但它们指向同一个对象并且打印 true

这是允许的,因为 ListMap 是接口。

我们可以想象一些 class

// (please only imagine)
class ListMap implements List, Map {...}

引用相等性的编译时合法性 (15.21.3) is the same as that of reference type casting (5.5.1)。简而言之,由于您通常可以在任何引用类型和接口之间进行转换,因此您通常也可以将任何类型的引用相等性与接口进行比较。

权限似乎在 ComparableSerializableIterable 等较小接口的上下文中更有用,其中 class 更有可能实现不止一个。

在Java中,只要你有对象,系统就会使用指针。当您在两个对象上使用 == 时,它会比较它们的 指针 。换句话说,它检查两个指针​​是否指向内存中的同一个对象。这始终是一个安全的检查。

另外,应该注意的是,当涉及继承(和polymorphism)时,可能有多个不同类型的指针指向同一个对象。当然,在您的示例中并非如此。但正如我之前所说,检查两个指针​​是否指向同一个对象是无害的,因为该检查不会对所涉及的 类 做出任何假设。