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

时间:2015-02-27 15:19:17

标签: java pointers types comparison

查看此代码段:

    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语言规范,所以这在规范中具有相当绝对的确定性,所以:

规范允许这样的内容有什么意义/目的/用途?

5 个答案:

答案 0 :(得分:4)

仅仅因为类型是不可转换的并不意味着不是平等的对象。如果类型是“不可转换的”,则意味着需要使用强制转换来检查类型是否实际可转换。

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

答案 1 :(得分:2)

特别允许,因为ListMap是接口。

我们可以设想一些课程

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

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

ComparableSerializableIterable等较小的界面环境中,权限似乎更有用,其中一个类更有可能实现多个。

答案 2 :(得分:1)

出现Incompatible types错误,因为在触发分配时,会启动名为Assignment conversion的操作。它的作用是:

  

当表达式的值被赋值(第15.26节)给变量时,就会发生赋值转换:必须将表达式的类型转换为变量的类型。

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

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:-5)

写作时

if(c==m)

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