为什么Java中不能切换不同的类? 每个类实例只存在一次,并且是一个不可变的常量。
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");
}
}
回答我自己的问题: 该用例似乎不够常见,因此支持此功能。目前(从 Java 18 开始)switch-case-语句支持切换文字:
它可以像instanceof运算符一样利用(详尽的)模式匹配,并且从Java 19开始,它将支持记录模式匹配,它可能会通过以下方式扩展:
未来的工作
这里描述的记录模式有很多方向 可以延长:
- 数组模式,其子模式与各个数组元素匹配;
- Varargs 模式,当记录是 varargs 记录时;
- 通用记录模式中类型参数的推断,可能使用菱形形式 (<>);
- 不关心模式,可以作为记录组件模式列表中的元素出现,但不声明模式变量;和
- 基于任意类而不仅仅是记录类的模式。
但目前看来,切换类的最佳方法是,就像 @Davide 指出的那样,使用唯一可识别的、人类可读的属性,例如它们的名称/路径。它本身会受到匿名类、隐藏类和本地类的限制。
有两个答案:
因为 Java 团队中没有人有足够的动力为更广泛的类型提出
switch
。 (用例并不常见......)
因为存在重大技术问题......
问题在于,
switch
语句需要case中的值是编译时常量表达式。 这是必要的,因为编译器必须能够检查不同情况下的值是否不同。 我们不能有这样的事情:
int A = 1;
int B = 1;
switch (foo) {
case A: doSomething(); break;
case B: doSomethingElse(); break;
}
编译时检查适用于整数和字符串值(常量表达式的结果)和枚举名称,因为这些类型具有相等模型1,将在编译时和运行时给出相同的答案。
不幸的是,这并不能推广到其他引用类型:
一方面,
==
在实践中很可能很难使用。
另一方面,编译器不可能执行编译时检查 case 值是成对的而不是彼此
equals
。
甚至类文字(例如
Foo.class
)也有问题2。 事实证明,如果同一个类由两个不同的类加载器加载,则可以获得两个不同的 Class
对象。 根据 ==
或 equals
,它们并不相等。 他们可能会想出一种适合编译时检查的语义。 但在上述场景中,运行时语义会遇到一个令人讨厌的问题。
1 - 请注意,使用
switch
的 String
语句/表达式的等式模型是 equals
,而不是 ==
。switch
值,但我可以理解为什么他们还没有这样做。
switch (myObject.getClass().getCanonicalName()) {
case "myFullClassName": ...
case "myOtherFullClassName": ...
}