被认为是不好的做法吗?如果是这样,在什么情况下仍然更可取?

时间:2010-05-01 16:37:57

标签: java instanceof

多年来,我尽可能避免instanceof。在适用的地方使用多态或访问者模式。我认为在某些情况下它只是简化了维护......是否还有其他一些应该注意的缺点?

但我确实在Java库中看到它,所以我认为它有它的位置?在什么情况下更可取?这是不可避免的吗?

7 个答案:

答案 0 :(得分:21)

它肯定在equals的股票实施中占有一席之地。 E.g。

public boolean equals ( Object o )
{
  if ( this == o )
  {
     return true;
  }

  if ( ! (o instanceof MyClass) )
  {
    return false;
  }

  // Compare fields
  ...
}

关于instanceof的一个巧妙的事情是它的LHS可以是null,在这种情况下,表达式的计算结果为false

答案 1 :(得分:12)

我认为当你绝对需要知道对象的类型时,instanceof是最好的选择。

一个不好的做法是拥有大量的instanceof,一个紧挨着另一个,并根据它们调用对象的不同方法(当然是强制转换)。 这可能反映出层次结构需要重新思考并可能重构。

答案 2 :(得分:11)

我可以想象一些情况,例如你有一些库的对象,你无法扩展(或者这样做会不方便),也许与你的一些对象混合,都有相同的基类,一起收集。
我想在这种情况下,使用instanceof来区分对这些对象的某些处理可能很有用。

同意维护遗留代码,你不能在很多旧类中注入一些新行为只是为了添加一个新的小功能或一些错误修复......

答案 3 :(得分:5)

当你进入一个纯粹的OO模型时,instanceof绝对是代码味道。

但是,如果你没有使用100%OO模型或者你需要从外部注入东西,那么instanceof或者等价物(isXXX()getType(),......)可以有它的用途。

一般的“规则”是尽可能避免它,特别是当控制类型层次结构并且可以使用子类型多态性时。我们的想法不是要问对象是什么类型并用它做某事,而是通过访问者(基本上是双重多态)直接或间接地询问对象来执行某些操作。

答案 4 :(得分:2)

我同意它可能有难闻的气味。很多例子,特别是在一块链接在一起的块,闻起来很糟糕。

有时候它会以你不会想到的方式行事......我曾经发生过一次:

Class B extends A
Class C extends A

B b = new B();
C c = new C();

b instanceof B -> true
b instanceof C -> true
c instanceof C -> true
c instanceof B -> true

(在我的情况下,这是由于hibernate制作代理对象而发生的......但只是在代码中依赖于instanceof的代码存在风险)

答案 5 :(得分:1)

它可以在铸造之前用作健全性检查;除了检查您的对象是否是正确类型之外,它还会检查它是否为空。

if (o instanceof MyThing) {
    ((MyThing) o).doSomething(); // This is now guaranteed to work.
} else {
    // Do something else, but don't crash onto ClassCast- or NullPointerException.
}

答案 6 :(得分:0)

创建工厂的情况如何? e.g。

public static Cage createCage(Animal animal) {
  if (animal instanceof Dog)
    return new DogHouse();
  else if (animal instanceof Lion)
    return new SteelCage();
  else if (animal instanceof Chicken)
    return new ChickenWiredCage();
  else if (animal instanceof AlienPreditor)
    return new ForceFieldCage();
  ...
  else
    return new GenericCage();
}