How to Use the Instanceof Operator in a Switch Statement

Is it possible to use the instanceof operator in a switch statement?

This is a typical scenario where subtype polymorphism helps. Do the following

interface I {
void do();
}

class A implements I { void do() { doA() } ... }
class B implements I { void do() { doB() } ... }
class C implements I { void do() { doC() } ... }

Then you can simply call do() on this.

If you are not free to change A, B, and C, you could apply the visitor pattern to achieve the same.

Can a switch statement be used to determine the class of an object?

For a switch to work the value must be a primitive value, a String or an Enum value.
In OO code switch statements are something of a code smell; generally indicating you have missed a chance to use polymorphism.

In functional languages you might be able to use a case statement to do what your are trying.

Java is OO so I would make use of polymorphism, you will have a cleaner design.

Polymorphism
Is an OO concept that basically says that two objects/classes can be considered to "BE" the same if one is the super set of the other. That is, if the objects/classes satisfy the IS-A relationship.
For example if you have a Car class, FastCar and VintageCar classes that extend Car both FastCar and VintageCar are Car classes and thus satisfy the IS-A relationship, and thus they can be used any where in code where Car can be called.
The implication here is that if Car...accelerate exists then FastCar.accelerate exists and can have different characteristics from VintageCar.accelerate so when call accelerate the code doesn't need to know the subtype but will call the correct accelerate method.

Switch type of Object in Java

The simply answer is: there is no switching on "type" in Java. In contrast to languages such as Scala, Java doesn't have an almost magic "pattern matching" feature.

When you really need to do that: figure the specific type of an Object instance, to then do different things based on the true nature of the object, such an if/else cascade is one of few choices.

One alternative is to use a map, like Map<Class<?>, Consumer<?>) or something alike. In other words: you (upfront) create a map that knows a method to call for different classes, and then do obj.getClass() to see if your map knows about that class. But that mechanism isn't very robust, as it only uses equals() for the class instances.

Beyond that: there are only very few selected use cases where such kind of "type switching" makes sense. Typically, you approach this problem ... by stepping back, looking at the real underlying problem and designing a completely different solution.

Why isn't it possible to switch over class objects?

To answer my own question:
The use case seems to be not common enough, that this feature is supported. Currently (as of Java 18) a switch-case-statement supports switching over literals:

  • primitive types
  • their wrapper classes
  • enum constants
  • String literals

It can utilize (exhaustive) pattern-matching like the instanceof operator, and as of Java 19 it will support record-pattern-matching which will maybe get extended by the following:

Future Work

There are many directions in which the record patterns described here
could be extended:

  • Array patterns, whose subpatterns match individual array elements;
  • Varargs patterns, when the record is a varargs record;
  • Inference for type arguments in generic record patterns, possibly using a diamond form (<>);
  • Do-not-care patterns, which can appear as an element in a record component pattern list but do not declare a pattern variable; and
  • Patterns based upon arbitrary classes rather than only record classes.

But currently it seems the best way to switch over classes would be, like @Davide pointed out, to use a uniquely identifieable, human-readable attribute, like their name/path. Which in itself would be restricted by anonymous, hidden, and local classes.



Related Topics



Leave a reply



Submit