假设我有这个类层次结构:
Animal <-- FourLegged <-- Dog
Animal <-- FourLegged <-- ....
Animal <-- ThreeLegged <-- ... (what has 3 legs?)
Animal <-- TwoLegged <-- Chicken
Animal <-- TwoLegged <-- ...
(忘记了四条腿和两条腿的动物的科学术语是什么。但这与重点无关,对吧?:(
如果我有一个Animal
对象,并且我需要知道它是FourLegged
还是TwoLegged
,那么我通常会执行animalObject instanceof FourLegged
。
这比在Animal
类中添加一堆isFourLegged()
、isThreeLegged()
、isTwoLegged()
慢吗
(我想知道性能的影响。这不是一个设计练习。所以如果你不浪费时间建议如何重写类,我将不胜感激(
编辑有些人建议添加"getNumberOfLegs((",这在这个特定的例子中是非常合理的。但假设重点不是要有腿的数量,而是要知道这是什么类型的动物。
如果子类没有添加任何行为,只是指定分支数的一种方式,则应该进行名为用字段替换子类的重构。=>不再需要子类了。
否则,添加一个多态方法,如:numberOfLegs()
,由Animal
的每个子类实现。
尝试
Animal animal = new Dog();
if(animal.getClass().isAssignableFrom(FourLegged.class)){
System.out.println("FourLegged");
}
以与其他相同的方式进行操作
问题集中在执行的"速度"上:一种方式比另一种方式慢吗?
除非您谈论的是算法差异,否则了解性能的唯一方法是测量您的预期用例。在Java中,许多变量都会影响性能,包括所选的JVM、JVM参数等等
话虽如此,很容易看出instanceof
可能还有更多的工作要做:
- 设置checkClass=this.getClass((
- checkClass==是目标类吗?如果是,返回true
- checkClass有超类吗?如果否,则返回false
- 设置checkClass=checkClass的超类
- 转到2
(可能会有更多的工作涉及接口的可能性;在这种情况下,我假设JVM实现意识到目标类不是接口,并且可以利用这些知识为其带来好处。(
然而,虚拟方法调用不需要潜在的迭代:从对象的vtable中获取函数指针,然后调用它
但是,当目标类是对象的直接超类时,在遍历类层次结构时只有一次迭代。这种情况比虚拟方法调用"更快"还是"更慢"?
一句话:这取决于情况。当性能很重要时,衡量。在没有明确指出代码性能瓶颈的数据的情况下,更喜欢清晰、简洁、可理解和可维护的代码。