Reputation: 817
Why isn't it possible to switch over different classes in Java? Every class-instance exists only once and is an immutable constant.
static void switchOnClass(Class<?> cls) {
switch (cls) {
case String.class -> System.out.println("String class");
case Integer.class -> System.out.println("Integer class");
default -> System.out.println("Unknown");
}
}
Upvotes: 1
Views: 3843
Reputation: 9766
Not exactly the question, but in most cases I assume you get the class from an object. With Java 21, if you want to switch on the class of an object you can write
static void switchOnClass(Object obj) {
switch (obj) {
case String s -> System.out.println("Object is a String");
case Integer -> System.out.println("Object is an Integer");
default -> System.out.println("Unknown");
}
}
Upvotes: 0
Reputation: 719248
There are two answers:
Because nobody on the Java team has been sufficiently motivated to propose switch
for a broader range of types. (Use-cases are uncommon ...)
Because there is a significant technical issue ...
The thing is that a switch
statement needs the values in the cases to be compile time constant expressions. This is necessary because the compiler has to be able to check that the values in different cases are distinct. We can't have something like this:
int A = 1;
int B = 1;
switch (foo) {
case A: doSomething(); break;
case B: doSomethingElse(); break;
}
The compile time checks work for integer and String values (that are results of constant expressions) and enum names because these types have models of equality1 that will give the same answer at compile time and runtime.
Unfortunately, this doesn't generalize to other reference types:
On the one hand, ==
would most likely be too difficult to use in practice.
On the other hand, it would not be possible for the compiler to perform a compile time check that the case values are pair-wise not equals
to each other.
Even class literals (e.g. Foo.class
) are problematic2. It turns out that if the same class is loaded by two different class loaders, you can get two distinct Class
objects. And they are NOT equal according to either ==
or equals
. They could probably come up with a semantic that was amenable to a compile time check. But the runtime semantics would have a nasty gotcha in the above scenario.
1 - Note that the equality model for switch
statements /expressions using String
is equals
, not ==
.
2 - I don't know if the Java language designers actually considered supporting switch
for Class
values, but I can understand why they haven't done it yet.
Upvotes: 2
Reputation: 817
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:
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.
Upvotes: 4
Reputation: 26926
It is not possible because is not part of the language.
As explained here on the oracle documentation:
A
switch
works with thebyte
,short
,char
, andint
primitive data types. It also works with enumerated types (discussed in Enum Types), the String class, and a few special classes that wrap certain primitive types: Character, Byte, Short, and Integer (discussed in Numbers and Strings).
Java is evolving through the years. The old versionsthe of switch doesn't allow to use the String
as parameter of the switch. May be thatin a newer version of java this functionality will be added, but for what I know at the moment it is not planned.
If you plan to use classes as business object of the switch you can use their full names and use the switch over strings
switch (myObject.getClass().getCanonicalName()) {
case "myFullClassName": ...
case "myOtherFullClassName": ...
}
Upvotes: 0