switch 语句中用于案例选择的常量映射?

Constant Map for case selection in switch statement?

有没有办法定义常量 Map 以便在 switch 语句中使用?我对来自 here, here 和其他人的静态地图的所有试验均未成功。为什么 Map 不是常量?

对于行 case (kws.get(KEYWORD_NAME)): 我总是得到 constant string expression required 错误。

public class Demo {

  public static final String KEYWORD_NAME = "Name";
  public static final String KEYWORD_TYPE = "Type";

  private static final Map<String, String> kws = Collections.unmodifiableMap(
  new HashMap<String, String>() {{
    put(KEYWORD_NAME, KEYWORD_NAME.toLowerCase());
    put(KEYWORD_TYPE, KEYWORD_TYPE.toLowerCase());
  }});

  public static void parse(String kw){
    switch(kw){
      case (kws.get(KEYWORD_NAME)):
        System.out.println("Test");
        break;
    default:
      System.out.println("Unknown");
    }
  }
}

否,因为 switch 语句中的 case 标签必须是常量表达式或枚举数。

对您的地图的引用是 final,并且您的地图不可修改。但后者在运行时间强制执行。编译器不会将该对象视为常量。

来自Java Language Specification, 14.11: The switch statement

SwitchLabel:
case ConstantExpression : 
case EnumConstantName : 
default :

常量表达式只能由原始字面量和字符串文字、某些没有副作用的运算符、常量变量和一些可以在编译时计算的其他组件组成。 (常量变量是已初始化为常量表达式的 final 原始类型或字符串类型的变量。)更多详细信息位于 15.28: Constant expressions.

我不知道你的用例,但你可以使用参数化枚举来代替不可修改的映射:

>> 当:

public enum Demo {
     NAME("Name"),
     TYPE("Type"),
     NOT_SUPPORTED("");

    private String code;
    private static final Map<String, Demo> CODE_VALUE_MAP = new LinkedHashMap<>();

    // -- static
    static {
        for (Demo demo : Demo.values()) {
            CODE_VALUE_MAP.put(demo.getCode(), demo );
        }
     }

   public static Demo forCode(@NotNull String code) {
        if (code!= null) {
            return CODE_VALUE_MAP.getOrDefault(code.toUpperCase(), NOT_SUPPORTED);
           }
           return NOT_SUPPORTED;
       }    
   }

   // -- constructor
   Demo(String code) {
       this.code= code;
   }

   // -- public methods
   public String getCode() {
       return code;
   }
}

>>然后:

...
public static void parse(String kw){
 Demo demo = Demo.forCode(kw);
 switch(demo){
  case NAME:
    System.out.println("Test");
    break;
default:
  System.out.println("Unknown");
}
...