72

多年来,我尽量避免instanceof。在适用的情况下使用多态性或访问者模式。我想它只是在某些情况下简化了维护......还有其他应该注意的缺点吗?

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

4

7 回答 7

23

它绝对在equals. 例如

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

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

  // Compare fields
  ...
}

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

于 2010-05-01T17:02:40.827 回答
15

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

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

于 2010-05-01T16:55:06.660 回答
13

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

一个不好的做法是有很多instanceofs,一个接一个,并根据它们调用对象的不同方法(当然是强制转换)。这可能反映了层次结构需要重新思考和重构。

于 2010-05-01T16:41:46.657 回答
6

当您在纯 OO 模型中时,那instanceof绝对是代码味道。

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

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

于 2010-05-01T16:56:20.027 回答
2

它可以很好地用作施法前的理智检查;除了检查您的对象是否是正确的类型之外,它还会检查它是否不为空。

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.
}
于 2010-05-01T16:50:11.707 回答
2

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

有时它会以你意想不到的方式表现......我曾经发生过的事情:

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的代码有风险的情况)

于 2010-05-01T21:17:54.720 回答
0

在创建工厂的情况下呢?例如

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();
}
于 2012-11-08T15:28:16.867 回答