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
The Difference Between the Runnable and Callable Interfaces in Java
Is a Java String Really Immutable
Specifying Java Version in Maven - Differences Between Properties and Compiler Plugin
Subclassing a Java Builder Class
Can Constructors Throw Exceptions in Java
Quickest Way to Find Missing Number in an Array of Numbers
How to Define a List Bean in Spring
Does a Tcp Socket Connection Have a "Keep Alive"
Converting Many 'If Else' Statements to a Cleaner Approach
Finding Key Associated with Max Value in a Java Map
How to Create Executable Java Program
How to Have 2 Jvms Talk to One Another
How to Set Up Jax-Rs Application Using Annotations Only (No Web.Xml)
Compile Code Fully in Memory with Javax.Tools.Javacompiler
What Makes Reference Comparison (==) Work for Some Strings in Java