查看此代码段:
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语言规范,所以这在规范中具有相当绝对的确定性,所以:
规范允许这样的内容有什么意义/目的/用途?
答案 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.
cs
和s
是不可转换的类型,但它们指向同一个对象并打印true
答案 1 :(得分:2)
特别允许,因为List
和Map
是接口。
我们可以设想一些课程
// (please only imagine)
class ListMap implements List, Map {...}
引用相等的编译时合法性(15.21.3)与引用类型转换(5.5.1)的合法时间相同。简而言之,由于您通常可以在任何引用类型和接口之间进行转换,因此通常也可以将任何类型的引用相等性与接口进行比较。
在Comparable
,Serializable
,Iterable
等较小的界面环境中,权限似乎更有用,其中一个类更有可能实现多个。
答案 2 :(得分:1)
出现Incompatible types
错误,因为在触发分配时,会启动名为Assignment conversion的操作。它的作用是:
当表达式的值被赋值(第15.26节)给变量时,就会发生赋值转换:必须将表达式的类型转换为变量的类型。
如果转换失败,则抛出编译时错误。
但是,== operator发生时不会抛出编译时错误。
答案 3 :(得分:1)
在Java中,只要有对象,系统就会使用指针。当您在两个对象上使用==
时,它会比较它们的指针。换句话说,它检查两个指针是否指向内存中的同一对象。这总是一个安全的检查。
此外,应该注意的是,当涉及继承(和polymorphism)时,可能有多个指向同一对象的不同类型的指针。当然,在您的示例中并非如此。但正如我之前所说,检查两个指针是否指向同一个对象是无害的,因为该检查不会对所涉及的类做出任何假设。
答案 4 :(得分:-5)
写作时
if(c==m)
你只是在检查@hashcode在某些情况下对于两个对象可能是相同的,所以你可能没有在该行中收到任何错误!