为什么......
String a = new String("a");
StringBuilder b = new StringBuilder("a");
System.out.println(a==b);
...在编译时会导致类型不兼容的错误......
String a = new String("b");
Object b = new StringBuilder("b");
System.out.println(a==b);
......不是吗?
为什么我可以比较String和Object的对象引用,但不能比较StringBuilder和String? Aren他们都只是在内存位置寻址吗?
由于
答案 0 :(得分:4)
根据Java语言规范(15.21.3):
如果无法通过强制转换(§5.5)将任一操作数的类型转换为另一种操作数的类型,那么这是一个编译时错误。两个操作数的运行时值必然是不相等的(忽略两个值都为null的情况)。
这意味着,为了“比较”两种引用类型,应该能够将其转换为另一种引用类型。字符串“是”一个对象,但String
和StringBuilder
之间没有“强制转换”。
答案 1 :(得分:3)
编译器会尝试帮助您。
当==
由于类型冲突而永远不会成立时,它会假定您犯了一个错误,并拒绝编译代码。
同时发生instanceof
,也发生演员表。
String a = null;
if (a instanceof StringBuilder){} // compile-error
StringBuilder b = (StringBuilder) a; // compile-error
答案 2 :(得分:3)
因为,String
是Object
,但String
不是StringBuilder
。您可以使用相同类型和超类型的==
来比较引用。请看下面的例子
class A{
}
class B extends A{
}
class C{
}
现在,
A a =new A();
A b =new B(); // or B b =new B();
C c= new C();
System.out.println(a==b); // It is ok
System.out.println(a==c); // It will generate compile time error
答案 3 :(得分:2)
String扩展Object
类型,与任何其他类一样,但不继承StringBuilder
。因此,在您的比较中,String
会回退到Object
,而 共有类型。
答案 4 :(得分:1)
因为Strings和StringBuilders都是Object
类的子类。但它们不是同一类,因此无法使用==
进行比较。您需要在toString
上调用StringBuilder
方法。
答案 5 :(得分:0)
在第二个例子中,String也是一个Object,因为所有类都是Object的子类,你可以检查它们是否为==。
在第一个示例中,您将String与StringBuilder进行比较,它们是不同的类,并且都不是另一个的子类,因此运算符失败。
答案 6 :(得分:0)
因为您必须比较兼容类型,因为比较不兼容类型的相等性始终为false
。
String
与Object
兼容,因此将引用与这些类型进行比较不是编译时错误。 StringBuilder
与Object
兼容,因此您可以将StringBuilder
分配给Object
类型的变量。但String
和StringBuilder
与彼此不兼容。因此,如果您有String
引用和Object
引用,则可以在没有编译时错误的情况下对它们进行比较。但是如果你有一个String
引用和一个StringBuilder
引用,你就不能 - 编译器知道比较永远不会是true
。
注意所有关于引用类型(变量)的内容,而不是分配给它们的对象的类型。这就是为什么它可以设置你的第二个场景并让它编译,即使它永远不会有真正的结果。