【问题标题】:why is there a compiler error in this instanceof test [duplicate]为什么在这个实例测试中存在编译器错误[重复]
【发布时间】:2013-10-01 12:34:33
【问题描述】:

我认为下面的代码会编译并打印“否”

class One{
 public static void main(String[] args) {

   One o = new One();
   if(o instanceof Two) {
     System.out.println("Yes");
   } else {
     System.out.println("No");
   }
 }
}

class Two { }

但它给我一个编译器错误,说明inconvertible types instanceof 运算符不应该检查对象是否在继承层次结构中,如果是则返回 true,如果不是则返回 false

编辑:

如果编译器已经知道某个条件永远不会为真并且它会引发编译器错误,那么为什么要编译这段代码

if(false) {
  System.out.println("Yes");
}

【问题讨论】:

  • 因为它可以从类名中看出答案是否定的。将 o 声明为 Object(但仍创建 One)。 Object o = new One();
  • @fvrgl :我没看到那个帖子,我的错。但你能看到我的编辑并提供解释吗?
  • 你在 if(false) 案例中没有违反任何规则。
  • JLS 声明:如果将 RelationalExpression 转换为 ReferenceType 将作为编译时错误被拒绝,那么 instanceof 关系表达式同样会产生编译时错误。在这种情况下,instanceof 表达式的结果永远不会为真。
  • JLS 非常明确且切中要害。

标签: java


【解决方案1】:

您收到该消息是因为编译器能够判断 o 不能是 Two 的实例,因为类 OneTwo 没有继承关系。

也许你打算写:

Object o = new One();

在这种情况下,您的测试将有意义。

【讨论】:

  • 请看我编辑的问题
【解决方案2】:

我相信这是因为您已将“o”变量声明为“One”类型。 将您的代码更改为此,它应该编译

   Object o = new One();
   if(o instanceof Two) {
     System.out.println("Yes");
   } else {
     System.out.println("No");
   }

instanceof 运算符是在您事先不知道类型时使用的。因此,当您有一个通过方法参数传入的对象时,或者当您的变量以基类的类型声明并希望每个子类类型具有不同的行为时。在您提供的场景中,编译器可以在编译时告诉您您编写的内容永远不会是真的,并且会这样做。

编辑:if(false) 编译,因为很多人使用这样的模式:

public class Application{

    private static final boolean DEBUG = true;

    public static void main(String args[]){
        if(DEBUG){
            System.out.println("Debugging information");
        }
    }
}

现在想象一个大型应用程序,其中这种模式在多个地方重复。如果编译器拒绝编译它,那么在 DEBUG 模式之间切换会更加困难。

在我之前的解释中,也许我不应该使用“编译器可以在编译时告诉你你写的永远不会是真的”这样的词。更好的描述应该是“编译器可以判断出你写的东西没有意义”。

【讨论】:

  • 请看我编辑的问题
  • 我已经编辑了我的答案
【解决方案3】:

instanceof 用于标识被另一个类的引用变量多态引用的对象,因此如果引用变量o 不能引用类Two 的对象,它将无法编译。

所以这个:

One o = new One();
if(o instanceof Two) {
    System.out.println("ok");
}

例如会出现类似这样的错误:

int i = 1;
if (i == "s") {
    System.out.println("ok");
}

根本无法编译!

编辑

一个多态性的例子,它可以让你的代码编译(根据其他人的答案):

Object o = new One();

因为o可以引用Two,所以instanceof会告诉你是否这样做。

【讨论】:

    【解决方案4】:

    首先对于上述程序,您将得到“不兼容的条件操作数类型一和二”,因为一和二没有任何关系。

    要使上面的程序结果为 True 应该是这样的,

    public class One {
        public static void main(String[] args) {
    
            One o = new Two();
            if (o instanceof Two) {
                System.out.println("Yes");
            } else {
                System.out.println("No");
            }
        }
    }
    
    class Two extends One {
    }
    

    这里,一是父母,二是孩子。父对象引用子对象,因此运算符实例将返回 true。

    【讨论】:

    • 我没有尝试打印“是”
    • 正如我在评论中提到的,没有父母和孩子的关系。对于使用instanceOf,引用类型和对象之间应该存在某种关系。在这里,一和二之间没有任何关系。
    猜你喜欢
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-17
    • 2019-10-03
    • 2019-11-29
    • 2016-04-07
    • 1970-01-01
    相关资源
    最近更新 更多