当我在对象中键入强制字符串时,以下运算符instanceof
工作正常。
但是,如果没有类型转换,它将无法编译。
public class Test {
public static void main(String[] args) {
boolean b1 = "abc" instanceof Integer; // Compilation fails
boolean b2 = ((Object) "abc") instanceof Integer; // Works fine
}
}
我的问题是为什么编译器拒绝第一个b1
但允许第二个b2
因为您已经将"abc"
转换为Object
,所以编译器将((Object) "abc")
与Object
类型的任何其他表达式相同。
因此,它认为它可以包含任何Object
(或空)。编译器不会深入检查表达式以确定更具体的类型。
你也可以写:
Object obj = "abc";
boolean b2 = obj instanceof Integer;
基本上是一样的。
它会阻止你编写"abc" instanceof Integer
,因为String
和Integer
都是类,它们是不相关的,所以String
永远不可能是Integer
的实例。(它将允许"abc" instanceof List
,因为List
是一个接口,它不考虑类的最终性,并假设可能存在一个可以实现List
的String
子类)。
从某种意义上说,强制转换是你告诉编译器你知道的比它知道的更多。尽管编译器能够在非常基本的情况下进行反击,它可以确定您正在做一些无意义的事情,但它在很大程度上避开并信任您(以"随你头吧"的方式)。
JLS 15.20和 15.20.2 声明如下:
RelationalExpression: ... RelationalExpression instanceof ReferenceType
如果
RelationalExpression
对ReferenceType
的强制转换将作为编译时错误被拒绝 (§15.16),则instanceof
关系表达式同样会产生编译时错误。在这种情况下,表达式实例的结果永远不可能是真的。
在你的第一个例子表达式 ("abc" instanceof Integer
) 中,"abc"
(String
) 不能强制转换为Integer
。 因此,instanceof
表达式是一个编译错误。
在第二个示例表达式 (((Object) "abc") instanceof Integer
中,左操作数的类型为Object
。 在某些情况下,Object
可能是Integer
。 因此,可以将左操作数转换为右手类型。 因此,允许instanceof
。
值得注意的是,JLS 只关注表达式的编译时类型。 在第二个示例中,我们可以很容易地推断出左操作数的运行时类型始终String
,表达式的计算结果始终为false
。 但是JLS规则并没有将这个"错误"归类为编译错误。
实例只能在父类和子类之间使用
第一个"abc"是字符串类型而不是整数。
但第二个((对象)"abc")是对象类型,整数是对象的子项