1

Say I have this class hierarchy:

Animal <-- FourLegged <-- Dog
Animal <-- FourLegged <-- ....

Animal <-- ThreeLegged <-- ... (what has 3 legs?)

Animal <-- TwoLegged <-- Chicken
Animal <-- TwoLegged <-- ...

(Forgot what the scientific terms for four-legged and two-legged animals are. But that's beside point, right? :) )

If I have an Animal object, and I need to know whether it is a FourLegged or if it is a TwoLegged, I would normally do animalObject instanceof FourLegged.

Is that slower than adding a bunch of isFourLegged(), isThreeLegged(), isTwoLegged(), to Animal class?

(I would like to know the performance impact. This is NOT a design exercise. So I would appreciate it if you won't be wasting time suggesting how to re-write the class)

Edit Some people have suggested adding 'getNumberOfLegs()", which is perfectly reasonably given this specific example. But suppose the point is NOT to have the number of legs, but to get what type of animal this is.

One Two Three
  • 22,327
  • 24
  • 73
  • 114

3 Answers3

1

If your subclasses doesn't add any behavior and is just a way to specify the number of legs, you should go with this refactoring called Replace Subclass With Fields. => no need for subclasses any more.

Otherwise, add a polymorphic method like: numberOfLegs(), implemented by each of your Animal's subclasses.

Mik378
  • 21,881
  • 15
  • 82
  • 180
  • Ok, I appreciate you taking time to answer my question. But I don't believe this actually responds to my question which is whether "instanceof" is slower. – One Two Three Apr 30 '14 at 18:55
  • With any good computer nowadays, instanceof is really not a problem. If you look at some advised refactoring made by Martin Fowler, you will notice that slowness isn't a true issue in 99% of cases. He doesn't hesitate to make a same loop twice or more, if the code could be really cleaner, for instance. – Mik378 Apr 30 '14 at 18:57
  • @OneTwoThree Look at the selected answer of this post: http://stackoverflow.com/questions/103564/the-performance-impact-of-using-instanceof-in-java – Mik378 Apr 30 '14 at 19:07
0

Try

    Animal animal = new Dog();

    if(animal.getClass().isAssignableFrom(FourLegged.class)){
        System.out.println("FourLegged");
    }

Do it in same way for others

Braj
  • 46,415
  • 5
  • 60
  • 76
  • 1
    Reflection and any similar stuff are the enemies of good design ;) IMO – Mik378 Apr 30 '14 at 18:54
  • Does `Class#isAssignableFrom()` use reflection? – Braj Apr 30 '14 at 18:55
  • it's just a "similar stuff" :) Essence of OO is: "I don't want to be forced to check before calling". – Mik378 Apr 30 '14 at 18:55
  • Ok, I appreciate you taking time to answer my question. But I don't believe this actually responds to my question which is whether "instanceof" is slower. – One Two Three Apr 30 '14 at 18:56
  • @Mik378 `isAssignableFrom`and `instanceof` really don't count--and your statement is too broad in any case. (Perhaps non-framework code should generally avoid reflection.) – chrylis -cautiouslyoptimistic- Apr 30 '14 at 18:57
  • @Mik378 can you share me any link where it's defined that `Class#isAssignableFrom()` uses reflection. – Braj Apr 30 '14 at 18:58
  • @Braj I didn't mean that isAssignableFrom is reflection. I just include this kind of stuff as being a "meta-data" (like reflection is) and any good design should avoid if possible. – Mik378 Apr 30 '14 at 18:59
  • @Braj When you write this: `animal.getClass().isAssignableFrom(FourLegged.class)`, you make your code really tied to the code structure. It'd be better to don't have any knowledge of the existence of the `FourLegged` class in the referential of the caller. Loose coupling is preferred in any cases. – Mik378 Apr 30 '14 at 19:09
0

The question centers around the "speed" of execution: Is one way slower than another?

Unless you're talking about algorithmic differences, the only way to know anything remotely accurate about performance is to measure your expected use case. In Java many variables affect performance, including the JVM chosen, JVM arguments, and so on.

Having said that, it is straightforward to see that instanceof potentially has more work to do:

  1. Set checkClass = this.getClass()
  2. Is checkClass == the target class? If yes, return true.
  3. Does checkClass have a superclass? If no, return false.
  4. Set checkClass = superclass of checkClass
  5. Goto 2

(With potentially more effort involving the possibility of interfaces; in this case I am presuming that the JVM implementation is aware that the target class is not an interface and can use that knowledge to its benefit.)

However, a virtual method call requires no potential iteration: Fetch a function pointer from the object's vtable, and call it.

But when the target class is the immediate superclass of the object, then there is only one iteration in traversing the class hierarchy. Is that case "faster" or "slower" than a virtual method call?

Bottom line: It depends. When performance matters, measure. In the absence of data clearly pointing to a performance bottleneck with the code, prefer code that is clear, concise, understandable, and maintainable.

Chuck Batson
  • 2,165
  • 1
  • 17
  • 15