需要有关运算符实例中的类型转换的信息



当我在对象中键入强制字符串时,以下运算符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,因为StringInteger都是类,它们是不相关的,所以String永远不可能是Integer的实例。(它将允许"abc" instanceof List,因为List是一个接口,它不考虑类的最终性,并假设可能存在一个可以实现ListString子类)。

从某种意义上说,强制转换是你告诉编译器你知道的比它知道的更多。尽管编译器能够在非常基本的情况下进行反击,它可以确定您正在做一些无意义的事情,但它在很大程度上避开并信任您(以"随你头吧"的方式)。

JLS 15.20和 15.20.2 声明如下:

RelationalExpression:
...
RelationalExpression instanceof ReferenceType

如果RelationalExpressionReferenceType的强制转换将作为编译时错误被拒绝 (§15.16),则instanceof关系表达式同样会产生编译时错误。在这种情况下,表达式实例的结果永远不可能是真的。

在你的第一个例子表达式 ("abc" instanceof Integer) 中,"abc"(String) 不能强制转换为Integer。 因此,instanceof表达式是一个编译错误。

在第二个示例表达式 (((Object) "abc") instanceof Integer中,左操作数的类型为Object。 在某些情况下,Object可能是Integer。 因此,可以将左操作数转换为右手类型。 因此,允许instanceof

值得注意的是,JLS 只关注表达式的编译时类型。 在第二个示例中,我们可以很容易地推断出左操作数的运行时类型始终String,表达式的计算结果始终为false。 但是JLS规则并没有将这个"错误"归类为编译错误。

实例只能在父类和子类之间使用

第一个"abc"是字符串类型而不是整数。
但第二个((对象)"abc")是对象类型,整数是对象的子项

最新更新