英文:
Use Enum with switch statement: constant expression required error
问题
我定义了一个枚举类 "TestEnvEnum",并定义了一个名为 "ConfigInit" 的类,该类调用了枚举类。
public enum TestEnvEnum {
ENV1("devEnv1"),
ENV2("devEnv2"),
ENV3("devEnv3");
private final String name;
TestEnvEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
}
public class ConfigInit {
static String envIndex = "1";
static String envProps = System.getProperties().getProperty("env");
public static void scfInit() {
switch (envProps) {
case TestEnvEnum.ENV2.name(): //错误:需要常量表达式
envIndex = "2";
break;
case TestEnvEnum.ENV3.name(): //错误:需要常量表达式
envIndex = "3";
break;
default:
envIndex = "1";
}
}
}
问题:如果我使用枚举,那么 case TestEnvEnum.ENV2.name() 和 case TestEnvEnum.ENV3.name() 会提示 "需要常量表达式" 错误。
如果我将它们改为 case "devEnv2" 和 case "devEnv3",程序将正确运行。
我想知道如何在我的程序中正确使用枚举以避免这种错误。请帮助我。
英文:
I've defined an enumerated class "TestEnvEnum", and I've defined a class "ConfigInit" that calls the enumerated class.
public enum TestEnvEnum {
ENV1("devEnv1"),
ENV2("devEnv2"),
ENV3("devEnv3");
private final String name;
TestEnvEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
}
public class ConfigInit {
static String envIndex = "1";
static String envProps = System.getProperties().getProperty("env");
public static void scfInit() {
switch (envProps) {
case TestEnvEnum.ENV2.name(): //error: Constant expression required
envIndex = "2";
break;
case TestEnvEnum.ENV3.name(): //error: Constant expression required
envIndex = "3";
break;
default:
envIndex = "1";
}
}
}
Question: If I using Enum, so case TestEnvEnum.ENV2.name() and case TestEnvEnum.ENV3.name() will prompt "Constant expression required".
If I changed them to case "devEnv2" and case "devEnv3", the program will run correctly.
I want to know how I should use Enum in my program to avoid such an error. Pls help me.
答案1
得分: 2
你可以将其更改为类似这样的形式:
public enum TestEnvEnum {
ENV1("devEnv1"),
ENV2("devEnv2"),
ENV3("devEnv3");
private final String name;
TestEnvEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
public static TestEnvEnum byName(String name) {
for (TestEnvEnum value : values()) {
if(value.getName().equals(name)) {
return value;
}
}
return null;
}
}
public class ConfigInit {
static String envIndex = "1";
static String envProps = System.getProperties().getProperty("env");
public static void scfInit() {
TestEnvEnum testEnvEnum = TestEnvEnum.byName(envProps);
switch (testEnvEnum) {
case ENV2:
envIndex = "2";
break;
case ENV3:
envIndex = "3";
break;
default:
envIndex = "1";
}
}
}
我建议您阅读此处的帖子这里,该帖子非常好地解释了为什么会发生这种情况。
英文:
You can change it to something like this:
public enum TestEnvEnum {
ENV1("devEnv1"),
ENV2("devEnv2"),
ENV3("devEnv3");
private final String name;
TestEnvEnum(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public String toString() {
return name;
}
public static TestEnvEnum byName(String name) { //You may change the return type to Optional<TestEnvEnum> to avoid NPE
for (TestEnvEnum value : values()) {
if(value.getName().equals(name)) { //equalsIgnoreCase should be used if you don't care about the capitalization
return value;
}
}
return null;
}
}
public class ConfigInit {
static String envIndex = "1";
static String envProps = System.getProperties().getProperty("env");
public static void scfInit() {
TestEnvEnum testEnvEnum = TestEnvEnum.byName(envProps);
switch (testEnvEnum) {
case ENV2:
envIndex = "2";
break;
case ENV3:
envIndex = "3";
break;
default:
envIndex = "1";
}
}
}
I would recommend you to read this post here which explains really good why this happens.
答案2
得分: 0
每个枚举值都有一个内置的ordinal(),从ENV1开始为0,因此在scfInit()的定义中不需要添加switch语句。
因此,如果您使用@CodeMatrix的回答中添加的TestEnvEnum.byName
代码,scfInit()的定义就会简单如下:
public static void scfInit() {
TestEnvEnum testEnvEnum = TestEnvEnum.byName(envProps);
envIndex = String.valueOf(testEnvEnum.ordinal() + 1);
}
英文:
Every Enum value has a built in ordinal() which starts from 0 for ENV1, so there no need to add a switch to definition of scfInit().
So if you use the TestEnvEnum.byName
code added by @CodeMatrix answer the definition of scfInit() is simply:
public static void scfInit() {
TestEnvEnum testEnvEnum = TestEnvEnum.byName(envProps);
envIndex = String.valueOf(testEnvEnum.ordinal()+1);
}
答案3
得分: -1
在你的用例中,它会响应正确的异常,因为你传递的是envProp
,它的类型是String,所以所有的情况都应该定义为字符串类型,但在你的情况下,你正在调用不支持的name()
方法来评估值,所以你要么需要将Enum类型传递给switch,以便它查找枚举,否则将你的枚举值转换为字符串,并在表达式的位置使用字符串常量。
注意:所有的case标签必须都是明确的枚举值,而不是评估为枚举值的表达式。
例如:
enum TestEnvEnum {
ENV1("devEnv1"),
ENV2("devEnv2"),
ENV3("devEnv3");
private final String name;
TestEnvEnum(String name) {
this.name = name;
}
public static TestEnvEnum enumValue(String name) {
return Arrays.stream(values())
.filter(value -> name.equalsIgnoreCase(value.name))
.findFirst()
.orElse(null);
}
@Override
public String toString() {
return name;
}
}
public class SampleEnum {
static String envIndex = "1";
public static void scfInit() {
TestEnvEnum envProps = TestEnvEnum.enumValue(System.getProperties().getProperty("env"));
switch (envProps) {
case ENV2:
envIndex = "2";
break;
case ENV3:
envIndex = "3";
break;
default:
envIndex = "1";
}
}
}
上面的示例将起作用。
英文:
In your use case, it is responding with correct exception as you are passing envProp
which is of type String so all the cases will we defined with string type but in your case you are evaluating the value by calling name()
method which is unsupported so either you need to pass Enum type the switch so that it looks for enums otherwise convert your enum values to a string and use strig constants in place of expression.
Note: The case labels must all be explicit enum values, not expressions that evaluate to enum values.
e.g.
enum TestEnvEnum {
ENV1("devEnv1"),
ENV2("devEnv2"),
ENV3("devEnv3");
private final String name;
TestEnvEnum(String name) {
this.name = name;
}
public static TestEnvEnum enumValue(String name) {
return Arrays.stream(values()).filter(value -> name.equalsIgnoreCase(value.name)).findFirst()
.orElse(null);
}
@Override
public String toString() {
return name;
}
}
public class SampleEnum {
static String envIndex = "1";
public static void scfInit() {
TestEnvEnum envProps = TestEnvEnum.enumValue(System.getProperties().getProperty("env"));
switch (envProps) {
case ENV2:
envIndex = "2";
break;
case ENV3:
envIndex = "3";
break;
default:
envIndex = "1";
}
}
}
The above example will work.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论