instanceof keyword usage

11,593

Solution 1

Generally speaking yes. It's best to keep all code that depends on being a specific class within that class, and using instanceof generally means that you've put some code outside that class.

Look at this very simple example:

public class Animal
{
}

public class Dog extends Animal
{
}

public class Cat extends Animal
{
}

public class SomeOtherClass
{
  public abstract String speak(Animal a)
  {
    String word = "";

    if (a instanceof Dog)
    {
      word = "woof";
    }
    else if (a instanceof Cat)
    {
      word = "miaow";
    }

    return word;
  }
}

Ideally, we'd like all of the behaviour that's specific to dogs to be contained in the Dog class, rather than spread around our program. We can change that by rewriting our program like this:

public abstract class Animal
{
  public String speak();
}

public class Dog extends Animal
{
  public String speak()
  {
    return "woof";
  }
}

public class Cat extends Animal
{
  public String speak()
  {
    return "miaow";
  }
}

public class SomeOtherClass
{
  public String speak(Animal a)
  {
    return a.speak();
  }
}

We've specified that an Animal has to have a speak method. Now SomeOtherClass doesn't need to know the particular details of each type of animal - it can hand that off to the subclass of Animal.

Solution 2

There are many good answers promoting virtual methods, but instanceof has its uses as well. Imagine that you iterate over List<Event>, to pick up all Urgent objects. You might do it using isUrgent() but I am not sure if it were necessarily more concise or readable. Also, isUrgent() would require making Event aware that its subclasses may possess the respective property, which might:

  • be regarded as something against modularity principles;
  • be even impossible, if Event belongs to some library that can not be modified.
  • Solution 3

    Favor polymorphism and dynamic binding to downcasting and instanceof. This is the "OO Way" and enables you to write code that doesn't need to know about subtypes.

    EXAMPLE

    abstract class Animal {
        public abstract void talk();
        //...
    }
    
    class Dog extends Animal {
        public void talk() {
            System.out.println("Woof!");
        }
        //...
    }
    
    class Cat extends Animal {
        public void talk() {
            System.out.println("Meow!");
        }
        //...
    }
    
    class Hippopotamus extends Animal {
        public void talk() {
            System.out.println("Roar!");
        }
        //...
    }
    
    class Main {
    
        public static void main(String[] args) {
    
            makeItTalk(new Cat());
            makeItTalk(new Dog());
            makeItTalk(new Hippopotamus());
        }
    
        public static void makeItTalk(Animal animal) {
    
            animal.talk();
        }
    }
    

    Solution 4

    Usage of instanceof is discouraged when same effect can be achieved via virtual methods, like in example of thomson_matt. However, it's necessary to use instanceof in some circumstances. For example, when your code gets Object from external source, say, network or third-party API which returns Object, and you must decide what is the type of this Object and act appropriately.

    Solution 5

    The key is to not see instanceof as being part of common "normal practice". Like introspection in general, instanceof is a special tool for use in particular, atypical circumstances. Whenever you do use 'instanceof', you may also find yourself using other 'special' parts of the platform such as reflection more generally.

    So long as whenever you find yourself using it you accept that what you're doing is a kludge in the absence of a more elegant/practical alternative, then that's fine.

    That said, the most typical circumstances in everyday programs are probably:

    • implementing equals()
    • reading serialized objects
    • a few other cases where you're given an array/collection of items, e.g. enumerating JComponents in a frame/container and then taking action depending on type.

    A rule of thumb you could try and stick to is to not require users of a library to have to use 'instanceof', but rather have any cases of 'instanceof' internal to the library.

    Or put another way, you should re-frame your question: "What are the cases that 'intsanceof' is a workaround for?"

    Share:
    11,593
    aps
    Author by

    aps

    Updated on June 04, 2022

    Comments

    • aps
      aps almost 2 years

      Is using the instanceof keyword against the essence of object oriented programming? I mean is it a bad programming practice? I read somewhere that using instanceof keyword means that the design may not be that good. Any better workaround?

    • thomson_matt
      thomson_matt almost 13 years
      I love the fact that we were writing these at the same time and both went for animal examples :)
    • tskuzzy
      tskuzzy almost 13 years
      I was just about to comment on the exact same thing on your post just as you commented on mine :)
    • adamjmarkham
      adamjmarkham almost 13 years
      Just as an extra point: As said in this answer a problem with instanceof is you need to specify the subtype. What if the subtypes change? Then you need to rewrite the instanceof tests. But if you use dynamic binding and polymorphism it won't make a difference and it will still work.
    • Clockwork-Muse
      Clockwork-Muse almost 13 years
      Should speak be abstract in Animal, or does every Animal start off mute?
    • aps
      aps almost 13 years
      thomson_matt has given a good example of bad usage of instanceof. Now I have a situation, where all the conditions he said, holds true. Say Animal is the Abstract Class, Cat and Dog are its subclasses. So naturally what sound each animal should make must be encapsulated in its own class itself. But let's say I have another class called Mouse who reacts to different animals in different ways.If it is a Dog, the Mouse doesn't do anything much except avoid the Dog's path.If it is a Cat, then it tries to hide.In such a situation, is it ok to instanceof, or is there some better method?
    • aps
      aps almost 13 years
      @AdamJMTech thomson_matt has given a good example of bad usage of instanceof. Now I have a situation, where all the conditions he said, holds true. Say Animal is the Abstract Class, Cat and Dog are its subclasses. So naturally what sound each animal should make must be encapsulated in its own class itself. But let's say I have another class called Mouse who reacts to different animals in different ways.If it is a Dog, the Mouse doesn't do anything much except avoid the Dog's path.If it is a Cat, then it tries to hide.How to handle such a situation using dynamic binding and polymorphism?
    • aps
      aps almost 13 years
      ...continued...Moreover I may have another class called Human who reacts to the different animals in ways different than the Mouse class.I might add a hundred other classes which react to different animals in different ways. There is it possible to handle the situation without instanceof?
    • Perception
      Perception almost 13 years
      I think 'bellow' would be a more appropriate phoneme for a hippo :). I'm going to subclass and override the default behaviour. +1 for your design allowing me to be able too.
    • adamjmarkham
      adamjmarkham almost 13 years
      @aps What happens when a Mouse or Human reacts? Does it call a method in the Animal class and the method call depends on the instance the Animal is?
    • aps
      aps almost 13 years
      @AdamJMTech No.To make it clearer,let's say you write an abstract class Animal and 3 classes which inherit Animal- Dog,Cat,Tiger. Now these three animals will only contain their inherent properties, like what sound they make, what they eat,how they attack prey etc.But how a Human class reacts to different animals is not defined in Animal(my situation is worse,in my case Human is not a subclass of Animal).So in the human class,I have to first test the object in front of me to see which animal it is and react accordingly.only instanceof comes to the rescue.any better solution?
    • thomson_matt
      thomson_matt almost 13 years
      You could have multiple reactTo(...) methods on the Mouse object, one for each animal type, and pass in the animal you want the mouse to react to.