多年来,我尽量避免instanceof
。在适用的情况下使用多态性或访问者模式。我想它只是在某些情况下简化了维护......还有其他应该注意的缺点吗?
但是,我确实在 Java 库中到处看到它,所以我想它有它的位置吗?在什么情况下更可取?这是不可避免的吗?
多年来,我尽量避免instanceof
。在适用的情况下使用多态性或访问者模式。我想它只是在某些情况下简化了维护......还有其他应该注意的缺点吗?
但是,我确实在 Java 库中到处看到它,所以我想它有它的位置吗?在什么情况下更可取?这是不可避免的吗?
它绝对在equals
. 例如
public boolean equals ( Object o )
{
if ( this == o )
{
return true;
}
if ( ! (o instanceof MyClass) )
{
return false;
}
// Compare fields
...
}
关于 instanceof 的一件好事是它的 LHS 可以是null
,在这种情况下,表达式的计算结果为false
。
我可以想象一些情况,例如你有一个库的一些对象,你不能扩展(或者这样做会不方便),可能与你的一些对象混合在一起,都具有相同的基类,一起在一个收藏。
我想在这种情况下,使用 instanceof 来区分对这些对象的某些处理可能很有用。
在遗留代码的一些维护中,您不能在许多旧类中注入一些新行为,只是为了添加一个新的小功能或一些错误修复......
我认为当你绝对需要知道一个对象的类型时,这instanceof
是最好的选择。
一个不好的做法是有很多instanceof
s,一个接一个,并根据它们调用对象的不同方法(当然是强制转换)。这可能反映了层次结构需要重新思考和重构。
当您在纯 OO 模型中时,那instanceof
绝对是代码味道。
但是,如果您没有使用 100% OO 模型,或者您需要从外部向其中注入东西,那么 instanceof 或等价物 ( isXXX()
, getType()
, ...) 可以有其用途。
一般的“规则”是尽可能避免它,特别是当您控制类型层次结构并且可以使用例如子类型多态性时。这个想法不是询问对象它是什么类型并用它做某事,而是通过访问者(本质上是双重多态性)直接或间接地询问对象以执行某些操作。
它可以很好地用作施法前的理智检查;除了检查您的对象是否是正确的类型之外,它还会检查它是否不为空。
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,特别是在一个链接在一起的 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的代码有风险的情况)
在创建工厂的情况下呢?例如
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();
}