views:

451

answers:

6

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?

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?

+2  A: 

I think that, when you certainly need to know the type of an object, instanceof is the best option available.

EDIT: ok, here you go downvoters.

A bad practice would be to have a lot of instances of, 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 more thinking and probably a refactoring.

Daniel Dolz
To the downvoters, leave comment!!! instanceof is just a tool, that can be missused. When you actually used it, it maybe a good practice or a bad practice, but that is not a problem of instanceof.
Daniel Dolz
Daniel, I'm not a downvoter here, but really, it's considered "bad form" to complain about downvoting. People downvote if they think your answer is incorrect or not useful. It's not a personal judgment. And it doesn't have to be explained or justified.
CPerkins
lol! did not know this StackOverflow etiquette! All right, I will not do it again.
Daniel Dolz
A: 

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.
}
Joonas Pulakka
I know very well what it does. I would say that your example exhibits a *bad practice* of instanceof. I would probably want to eliminate that conditional using polymorphism as described [here](http://sourcemaking.com/refactoring/replace-conditional-with-polymorphism)
aioobe
@aioobe in equals(Object o) you don't know :)
extraneon
Well, the example in that link is (in addition to being overly complex) prone to simple nullpointer crash. I prefer simple and robust solutions over fancy words.
Joonas Pulakka
+1  A: 

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.

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

PhiLho
I think in general, instanceof is most useful when dealing with APIs or libraries that you don't control.
tster
Ok, so due to legacy code. Fair enough. Still, it feels like such use of instanceof "fixes" previously not completely throught through design decisions.
aioobe
+1  A: 

When you are inside a pure OO model, then instanceof is definitely a code smell.

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.

The general "rule" would be to avoid it whenever possible, especially when you control 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.

eljenso
+7  A: 

It's definitely has its place in a stock implementation of equals. E.g.

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.

Alexander Pogrebnyak
_that_ gives me the creeps for more than 10 years in the code base I have to work with. Equality should not be defined (in most cases) on the type of objects, but on their behavior. `MyClass` is an implementation that can behave totally equal as e.g. a sibling `CacheMyClass` object! I wish I could -2 you for it :)Hmmm.... unless `instanceof` means 'implements' in this case, in which case it _may_ make sense...
xtofl
I find the use of "instanceof" in equals() acceptable because it's impossible extend an instantiable class and add an aspect (e.g., a new field) while preserving the equals() contract (particularly symmetry and transitivity). See Bloch's "Effective Java".
Steve Emmerson
A: 

I agree it can have a bad smell. Lots of instanceof, expecially in a chained together if block, smells of bad.

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)

bwawok