Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding instanceof in Java

Having a chain of "instanceof" operations is considered a "code smell". The standard answer is "use polymorphism". How would I do it in this case?

There are a number of subclasses of a base class; none of them are under my control. An analogous situation would be with the Java classes Integer, Double, BigDecimal etc.

if (obj instanceof Integer) {NumberStuff.handle((Integer)obj);} else if (obj instanceof BigDecimal) {BigDecimalStuff.handle((BigDecimal)obj);} else if (obj instanceof Double) {DoubleStuff.handle((Double)obj);} 

I do have control over NumberStuff and so on.

I don't want to use many lines of code where a few lines would do. (Sometimes I make a HashMap mapping Integer.class to an instance of IntegerStuff, BigDecimal.class to an instance of BigDecimalStuff etc. But today I want something simpler.)

I'd like something as simple as this:

public static handle(Integer num) { ... } public static handle(BigDecimal num) { ... } 

But Java just doesn't work that way.

I'd like to use static methods when formatting. The things I'm formatting are composite, where a Thing1 can contain an array Thing2s and a Thing2 can contain an array of Thing1s. I had a problem when I implemented my formatters like this:

class Thing1Formatter {   private static Thing2Formatter thing2Formatter = new Thing2Formatter();   public format(Thing thing) {       thing2Formatter.format(thing.innerThing2);   } } class Thing2Formatter {   private static Thing1Formatter thing1Formatter = new Thing1Formatter();   public format(Thing2 thing) {       thing1Formatter.format(thing.innerThing1);   } } 

Yes, I know the HashMap and a bit more code can fix that too. But the "instanceof" seems so readable and maintainable by comparison. Is there anything simple but not smelly?

Note added 5/10/2010:

It turns out that new subclasses will probably be added in the future, and my existing code will have to handle them gracefully. The HashMap on Class won't work in that case because the Class won't be found. A chain of if statements, starting with the most specific and ending with the most general, is probably the best after all:

if (obj instanceof SubClass1) {     // Handle all the methods and properties of SubClass1 } else if (obj instanceof SubClass2) {     // Handle all the methods and properties of SubClass2 } else if (obj instanceof Interface3) {     // Unknown class but it implements Interface3     // so handle those methods and properties } else if (obj instanceof Interface4) {     // likewise.  May want to also handle case of     // object that implements both interfaces. } else {     // New (unknown) subclass; do what I can with the base class } 
like image 728
Mark Lutton Avatar asked May 07 '10 16:05

Mark Lutton


People also ask

What can be used instead of Instanceof in Java?

The isInstance method is equivalent to instanceof operator. The method is used in case of objects are created at runtime using reflection.

Why you should not use Instanceof?

The problem with instanceof is that if you have a large amount of Animal s, you'll end up with a long if-else-if for every one of them. It's hard to maintain and prone to errors where e.g. a new type of Animal is added, but you forget to add it to the if-else-if chain.

Is it good to use Instanceof in Java?

Probably most of you have already heard that using “instanceof” is a code smell and it is considered as a bad practice. While there is nothing wrong in it and may be required at certain times, but the good design would avoid having to use this keyword.

Should you use instance of?

instanceof is a binary operator we use to test if an object is of a given type. The result of the operation is either true or false. It's also known as a type comparison operator because it compares the instance with the type. Before casting an unknown object, the instanceof check should always be used.


1 Answers

You might be interested in this entry from Steve Yegge's Amazon blog: "when polymorphism fails". Essentially he's addressing cases like this, when polymorphism causes more trouble than it solves.

The issue is that to use polymorphism you have to make the logic of "handle" part of each 'switching' class - i.e. Integer etc. in this case. Clearly this is not practical. Sometimes it isn't even logically the right place to put the code. He recommends the 'instanceof' approach as being the lesser of several evils.

As with all cases where you are forced to write smelly code, keep it buttoned up in one method (or at most one class) so that the smell doesn't leak out.

like image 120
DJClayworth Avatar answered Sep 26 '22 00:09

DJClayworth