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

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

但是我确实在 Java 库中看到了它的一些地方,所以我想它应该有它的位置吧?在什么情况下最好?这是不可避免的吗?

42261 次浏览

我认为,当您绝对需要知道对象的类型时,instanceof是可用的最佳选项。

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

它可以很好地用作强制转换之前的健全性检查; 除了检查对象的类型是否正确之外,它还可以检查对象是否为空。

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.
}

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

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

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

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

一般的“规则”是尽可能避免这种情况,特别是当 控制类型层次结构并且可以使用子类型的时候。其思想不是询问对象是什么类型并对其进行处理,而是通过访问者(本质上是双重多态性)直接或间接地请求对象执行某些操作。

它肯定在 equals的股票实现中占有一席之地。

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


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


// Compare fields
...
}

关于 instanceof 有一点需要注意,它的 LHS 可以是 null,在这种情况下,表达式的计算结果为 false

我同意它有一股难闻的气味。大量的实例,尤其是在一个链接在一起的块,闻起来很糟糕。

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

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

(在我的例子中,这是由于休眠使代理对象..。但仅仅是代码依赖于 instanceof 的情况是有风险的)

如果是创作工厂呢? 例如:。

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();
}