为什么不能切换类对象?

问题描述 投票:0回答:4

为什么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 switch-statement
4个回答
4
投票

回答我自己的问题: 该用例似乎不够常见,因此支持此功能。目前(从 Java 18 开始)switch-case-语句支持切换文字:

  • 原始类型
  • 他们的包装类
  • 枚举常量
  • 字符串文字

它可以像instanceof运算符一样利用(详尽的)模式匹配,并且从Java 19开始,它将支持记录模式匹配,它可能会通过以下方式扩展:

未来的工作

这里描述的记录模式有很多方向 可以延长:

  • 数组模式,其子模式与各个数组元素匹配;
  • Varargs 模式,当记录是 varargs 记录时;
  • 通用记录模式中类型参数的推断,可能使用菱形形式 (<>);
  • 不关心模式,可以作为记录组件模式列表中的元素出现,但不声明模式变量;和
  • 基于任意类而不仅仅是记录类的模式。

但目前看来,切换类的最佳方法是,就像 @Davide 指出的那样,使用唯一可识别的、人类可读的属性,例如它们的名称/路径。它本身会受到匿名类、隐藏类和本地类的限制。


1
投票

有两个答案:

  1. 因为 Java 团队中没有人有足够的动力为更广泛的类型提出

    switch
    。 (用例并不常见......)

  2. 因为存在重大技术问题......

问题在于,

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
,而不是
==

2 - 我不知道 Java 语言设计者是否真的考虑过支持
switch
值,但我可以理解为什么他们还没有这样做。

    


0
投票

here

在 oracle 文档中的解释:

A

Class 适用于

switch
byte
short
char
原始数据类型
。它还适用于
枚举类型
(在枚举类型中讨论)、字符串类以及一些包装某些原始类型的特殊类:字符、字节、短整型和整数(在数字和字符串中讨论)。

Java 多年来一直在发展。旧版本的开关不允许使用
int

作为开关的参数。可能在较新版本的 java 中会添加此功能,但据我目前所知,这还没有计划。


如果您计划使用类作为切换的业务对象,您可以使用它们的全名并使用字符串切换

String



0
投票

switch (myObject.getClass().getCanonicalName()) { case "myFullClassName": ... case "myOtherFullClassName": ... }

	
© www.soinside.com 2019 - 2024. All rights reserved.