【问题标题】:Why does this instanceof code work and does not cause a compile time error?为什么这个 instanceof 代码可以工作并且不会导致编译时错误?
【发布时间】:2010-10-09 19:04:45
【问题描述】:

在下面的代码中,x 的类型是 I(虽然 x 也实现了 J,但在编译时不知道)那么为什么 (1) 处的代码不会导致编译时错误。 因为在编译时只考虑引用的类型。

public class MyClass {
    public static void main(String[] args) {
        I x = new D();
        if (x instanceof J) //(1)
            System.out.println("J");
    }
}

interface I {}

interface J {}

class C implements I {}

class D extends C implements J {}

【问题讨论】:

  • 附注 - 请不要忘记为语言添加标签。我为你添加了“java”。

标签: java instanceof


【解决方案1】:

instanceof 用于在运行时确定对象的类型。您正在尝试在程序运行时确定x 是否真的是J 类型的对象,因此它会编译。

您是否认为它应该导致编译时错误,因为您认为编译器不知道 x 的类型?

编辑

正如 Kirk Woll 所评论的(感谢 Kirk Woll!),如果您正在检查 x 是否是 instanceof 一个具体类,并且编译器可以确定 x 的类型,那么您将收到错误消息在编译时。

来自 Java 语言规范:

如果将 RelationalExpression 转换为 ReferenceType 将作为编译时错误被拒绝,则 instanceof 关系表达式同样会产生编译时错误。在这种情况下,instanceof 表达式的结果永远不会为真。

作为一个例子:

import java.io.Serializable;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;

class SerializableClass implements Serializable
{
   private writeObject(ObjectOutputStream out) {}
   private readObject(ObjectInputStream in) {}
}

public class DerivedSerializableClass extends SerializableClass
{
   public static void main(String[] args)
   {
      DerivedSerializableClass dsc = new DerivedSerializableClass();

      if (dsc instanceof DerivedSerializableClass) {} // fine
      if (dsc instanceof Serializable) {} // fine because check is done at runtime
      if (dsc instanceof String) {} // error because compiler knows dsc has no derivation from String in the hierarchy

      Object o = (Object)dsc;
      if (o instanceof DerivedSerializableClass) {} // fine because you made it Object, so runtime determination is necessary
   }
}

【讨论】:

  • +1,如果它不是一个运行时操作符,它到底有什么意义呢?使用它的 if 语句毫无意义。
  • 好吧,根据我的阅读,使用 instanceof 运算符时会进行初始编译时检查,以确定源和目标是否具有子类型-超类型关系。然后根据源的实际对象来判断源是否是Destination类型的子类型。
  • 请纠正我对这应该如何工作的理解。所以在这段代码中,虽然 x 引用的对象是 J 的子类型,但 I 和 J 之间没有关系。所以由于 x 在上面的代码中属于 I 类型,即 I x = new D();,应该这样玩编译时的角色?
  • @user439526,啊,这就是你的意思。好点子。您的示例没有看到问题的原因是您在 interfaces 而不是在 classes 上使用 instanceof。编译器永远无法知道给定类型是否实现接口,因为潜在的子类可以实现它。正如您所指出的,这与类不同,如果您的示例使用了两个不兼容的类而不是接口,那么您确实会遇到编译器错误。
  • 你能用一个例子来说明这一点
【解决方案2】:

instanceof 是运行时操作符,而不是编译时操作符,因此使用被引用对象的实际类型对其进行评估。

【讨论】:

  • 是的,如果它获得静态输入(即类而不是引用)。我应该编辑我的答案,虽然 kuropenguin 已经给出了一个非常详尽的答案,所以这没有实际意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-05-23
  • 2020-04-26
  • 2011-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-09
相关资源
最近更新 更多