【问题标题】:Weird behaviour of if(x instanceof X)if(x instanceof X) 的奇怪行为
【发布时间】:2013-05-01 17:23:21
【问题描述】:

我有一个类PartA 和一个类PartB,它是PartA 的派生类。 我有一个PartA 类型的列表,其中包含a 和b 部分。 当我遍历它时,我需要确定它实际上是哪种类。 但如果我这样做:

for (PartA i : parts) {
    if (i instanceof PartA) {
        //some logic
    }

无论它实际上是哪个类,它仍然会返回 true:a 或 b。

我做错了什么,如果没有,我可以做些什么来达到预期的结果?

【问题讨论】:

  • 请参考一些好的java书籍来理解继承和instanceof操作符

标签: java class inheritance instanceof


【解决方案1】:

PartB 的实例也是PartA 的实例。始终首先检查最派生的类型。 (将instanceof X 读作“是X 的实例或X 的派生类型。”)

或者,更好的是,使用多态对你有利——这个逻辑可以移动到PartA的方法中,你可以覆盖PartB吗?然后您就不必实际测试对象的类型,您只需让虚拟方法调度为您解决这个问题。

【讨论】:

  • 通常我确实使用多态,但这是用于赋值,这是我第一次使用 instanceof 东西。所以我对它的工作原理有点困惑。感谢您的清晰解释。
【解决方案2】:

此行为是设计使然。
B 的实例也是A 的实例。

你想要

if (i.getClass() == A.class)

【讨论】:

  • @NewProger 我想他的意思是(i.getClass() == PartA.class)
  • @cdhowie 这显然是我所做的,但它给了我这个错误。
  • @cdhowie 哦,对不起,我的错误。现在可以了:)谢谢你们:)
【解决方案3】:

这里 instanceof 的行为与 JLS15.20.2 中指定的一样。据此:

在运行时,instanceof 运算符的结果为真,如果 RelationalExpression 的值不为空,并且引用可以 被强制转换(§15.16)到 ReferenceType 而不引发 类转换异常。否则结果为假。

在您的情况下,i 是引用,它是引用类型 PartA 的子类型。因此它总是返回true。你应该使用:

 if((i.getClass().getName()).equals(A.class.getName()))

【讨论】:

  • 我明白了,这只是我第一次使用“instanceof”。所以我对它的工作原理有点困惑。谢谢你清楚的解释。我应该更仔细地阅读 java 文档...
  • 比较类名似乎没有必要。
  • 我认为这是一个很好的解决方案,因为它非常简单并且确实解决了问题。但我敢肯定,甚至可以有其他方法来做到这一点,例如在其他答案中给出的那样。
  • 有什么理由比较类名称而不是类本身?
  • @JanDvorak: 是的。鉴于i 是子类ChildA 的对象,也是ChildA 的引用.. i.getClass() == A.class 是无效的比较。如果您确实显示它显示编译时错误:无法比较的类型:java.lang.Class<capture#734 of ? extends ChildA> and java.lang.Class<A>.. 其中ChildA 是类A 的子类。我认为比较类的名称适用于所有情况..
【解决方案4】:

鉴于您从PartA 继承的PartBPartB PartA,所以a instanceof PartA 将永远是true。要区分它们,您需要测试它是否为PartB

【讨论】:

  • 我明白了。我只是想它测试你要求它的确切课程,但正如你和其他人解释的那样,它的行为与我的预期不同。
  • 是的,我有正确的解释为什么它总是返回true,但是@SLaks 和@cdhowie 有更好的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-18
  • 1970-01-01
  • 1970-01-01
  • 2011-12-26
相关资源
最近更新 更多