Java instanceof 被认为是不好的做法吗?如果是这样,在什么情况下 instanceof 仍然更可取?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2750714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is instanceof considered bad practice? If so, under what circumstances is instanceof still preferable?
提问by aioobe
Over the years, I've tried to avoid instanceof
whenever possible. Using polymorphism or the visitor pattern where applicable. I suppose it simply eases maintenance in some situations... Are there any other drawbacks that one should be aware of?
多年来,我尽量避免instanceof
。在适用的情况下使用多态或访问者模式。我想它只是在某些情况下简化了维护......还有其他应该注意的缺点吗?
I do however see it here and there in the Java libraries so I suppose it has its place? Under what circumstances is it preferable? Is it ever unavoidable?
然而,我确实在 Java 库中到处看到它,所以我想它有它的位置吗?在什么情况下更可取?它永远是不可避免的吗?
采纳答案by PhiLho
I can imagine some cases, for example you have some objects of a library, which you can't extend (or it would be inconvenient to do so), perhaps mixed with some objects of your, all with same base class, together in a collection.
I suppose that in such case, using instanceof to distinguish some processing on these objects might be useful.
我可以想象一些情况,例如你有一些库的对象,你不能扩展(或者这样做会不方便),可能与你的一些对象混合在一起,所有对象都具有相同的基类,一起在一个收藏。
我想在这种情况下,使用 instanceof 来区分对这些对象的某些处理可能会很有用。
Idem in some maintenance of legacy code where you cannot inject some new behavior in lot of old classes just to add a new little feature or some bug fix...
在一些遗留代码的维护中,你不能在许多旧类中注入一些新行为只是为了添加一个新的小功能或一些错误修复......
回答by Daniel Dolz
I think that when you absolutely need to know the type of an object, instanceof
is the best option available.
我认为当您绝对需要知道对象的类型时,这instanceof
是可用的最佳选择。
A bad practice would be to have a lot of instanceof
s, one next to the other, and according to them call different methods of the objects (of course casting).
This would probably reflect that the hierarchy needs rethinking and probably refactoring.
一个不好的做法是有很多instanceof
s,一个挨着另一个,并根据它们调用对象的不同方法(当然是铸造)。这可能反映了层次结构需要重新思考和重构。
回答by Joonas Pulakka
It can well be used as a sanity check before casting; in addition to checking that your object is of right type, it also does check that it's not null.
它可以很好地用作铸造前的健全性检查;除了检查您的对象是否为正确类型外,它还检查它是否不为空。
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.
}
回答by eljenso
When you are inside a pure OO model, then instanceof
is definitely a code smell.
当您处于纯 OO 模型中时,instanceof
绝对是代码异味。
If, however, you are not using a 100% OO model or you need to inject stuff into it from the outside, then instanceof or equivalents (isXXX()
, getType()
, ...) can have its uses.
但是,如果您没有使用 100% OO 模型,或者您需要从外部向其中注入内容,则 instanceof 或等价物 ( isXXX()
, getType()
, ...) 可以发挥作用。
The general "rule" would be to avoid it whenever possible, especially when youcontrol the type hierarchy and can use subtype polymorphism for example. The idea is not to ask the object what type it is and do something with it, but rather to ask the object directly or indirectly via a Visitor (essentially double polymorphism) to perform some action.
一般的“规则”是尽可能避免它,尤其是当您控制类型层次结构并且可以使用子类型多态时。这个想法不是询问对象它是什么类型并用它做一些事情,而是通过访问者(本质上是双多态性)直接或间接地要求对象执行一些操作。
回答by Alexander Pogrebnyak
It's definitely has its place in a stock implementation of equals
. E.g.
它在equals
. 例如
public boolean equals ( Object o )
{
if ( this == o )
{
return true;
}
if ( ! (o instanceof MyClass) )
{
return false;
}
// Compare fields
...
}
One neat thing to know about instanceof is that its LHS can be null
and in that case the expression evaluates to false
.
关于 instanceof 需要了解的一件巧妙的事情是它的 LHS 可以是null
,在这种情况下,表达式的计算结果为false
。
回答by bwawok
I agree it can have a bad smell. Lots of instanceof, expecially in a chained together if block, smells of bad.
我同意它可能有难闻的气味。很多实例,特别是在一个链接在一起的 if 块中,闻起来很糟糕。
Sometimes it can behave in ways you would not expect... Something I had happen once:
有时它会以你意想不到的方式表现......我曾经发生过的事情:
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
(in my case this happened due to hibernate making proxy objects.... but just a case where code dpending on instanceof is risky)
(在我的情况下,这是由于休眠制作代理对象而发生的......但只是在 instanceof 上的代码有风险的情况)
回答by Thor
How about in the case of a creation factory? 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();
}