是否可以在java switch/case语句中使用类名?

是否可以在java switch/case语句中使用类名?,java,switch-statement,constants,final,class-names,Java,Switch Statement,Constants,Final,Class Names,我想使用javaswitch语句,它使用class名称作为case常量。有可能吗?或者我必须复制类名吗 由于编译器错误,以下代码无法工作: 大小写表达式必须是常量表达式 下面是这个问题的在线演示(openjdk 1.8.0_45):为什么不将映射存储在映射中,而不用开关 创建字符串到整数的映射,并将所有类名映射到它们的返回值 在请求时,如果条目不存在,则返回默认值。否则,返回映射中的值。而不是Switch..case为什么不使用If..Else。在我知道之前,应该可以在所有版本的java中工作

我想使用java
switch
语句,它使用
class
名称作为
case
常量。有可能吗?或者我必须复制类名吗

由于编译器错误,以下代码无法工作:

大小写表达式必须是常量表达式


下面是这个问题的在线演示(
openjdk 1.8.0_45
):

为什么不将映射存储在映射中,而不用开关

创建字符串到整数的映射,并将所有类名映射到它们的返回值


在请求时,如果条目不存在,则返回默认值。否则,返回映射中的值。

而不是Switch..case为什么不使用If..Else。在我知道之前,应该可以在所有版本的java中工作

if (tableName.equals(MyClass1.class.getSimpleName())) {
     return 1;
} else if (tableName.equals(MyClass2.class.getSimpleName())) {
     return 2;
} else {
     return Integer.MAX_VALUE;
}

编译器错误已经说明了这一点。大小写标签必须是常量表达式,类文本或对其调用
getSimpleName()
的结果都不是常量表达式

一个有效的解决办法是:

String tableName = "MyClass1";
...
switch (tableName) {
    case "MyClass1":
        return 1;
    case "MyClass2":
        return 2;
    default:
        return Integer.MAX_VALUE;
}
表达式
MyClass1.class.getSimpleName()
并不比
“MyClass1”
简单,但是,当然,不会有任何编译时检查名称是否与现有类匹配,重构工具或混淆器不会注意到类
MyClass1
和字符串文本
“MyClass1”

对于这个问题没有解决方案,你唯一能做的就是在关联类中声明键来记录一个关系,例如

class MyClass1 {
    static final String IDENTIFIER = "MyClass1";
    ...
}
class MyClass2 {
    static final String IDENTIFIER = "MyClass2";
    ...
}
...
String tableName = MyClass1.IDENTIFIER;
...
switch (tableName) {
    case MyClass1.IDENTIFIER:
        return 1;
    case MyClass2.IDENTIFIER:
        return 2;
    default:
        return Integer.MAX_VALUE;
}

这记录了与读取器的关系,但工具仍然无法确保实际字符串内容与类名匹配。但是,根据您想要实现的目标,现在可能变得无关紧要,字符串内容是否与类名匹配…

您可以尝试将字符串赋给最终的字符串局部变量吗?哪个jav版本?您在Java 7/8上会得到不同的结果。@Marged我正在使用Java 8,但对这两个版本的解决方案感兴趣…相关:编译时常量表达式的很好解释:我在考虑这个解决方案,但切换是否会更有效?也许,但您的代码也会因为需要lin而可读性较差每一个类名都是e,然后每种情况都是e。你得到的几纳秒的优化可能永远都不值得你使用
映射所能得到的干净的代码。哦,我忘了添加。如果我没记错的话,
在字符串上切换
es,除非最近有什么改变。谢谢你的评论+1,但我很抱歉我仍然好奇开关是否能为我工作。我真的不喜欢
否则如果
语句,请参阅@Sam Sunis提供的基于
Map
的解决方案,但直到我知道这在所有版本中都受支持,并且您将不需要处理任何版本依赖关系。此解决方案的问题是,在最坏的情况下,它没有o仔细考虑每一种可能性,这就是人们想要“switch”的原因。据我记忆所及,java中的switch case只是if/then/else的糖,编译的代码就是这样。这对我来说是正确的答案:case标签必须是常量表达式,而不是类文本,也不是调用
getSimpleName()的结果
在它们上面是常量表达式。这里可以找到编译时常量表达式的很好的解释:我原以为类文本是常量表达式,但后来
““+MyClass1.class
应该可以工作,但它不能……更违反直觉的是,
enum
常量引用不是编译时常量。它们可以在标签和注释中使用,但这是使用规则的例外(尽管不是编译时常量,但也可以在注释中使用类文本)。所以当你说
final EnumType X=EnumType.FOO
,则
X
将不是编译时常量,并且不能用作
大小写
标签(与基元类型和
字符串
不同)。底线是只有原语类型和
String
s可以是编译时常量(因为规范这么说)。@MasterJoe2在Eclipse的情况下,它将识别
MyClass2.IDENTIFIER
作为
MyClass2
的用法。如果没有源代码,它就不起作用,但仍然不是一个简单的文本搜索。如果您指的是第一种变体,那么答案中已经描述了这些限制。
class MyClass1 {
    static final String IDENTIFIER = "MyClass1";
    ...
}
class MyClass2 {
    static final String IDENTIFIER = "MyClass2";
    ...
}
...
String tableName = MyClass1.IDENTIFIER;
...
switch (tableName) {
    case MyClass1.IDENTIFIER:
        return 1;
    case MyClass2.IDENTIFIER:
        return 2;
    default:
        return Integer.MAX_VALUE;
}