【问题标题】:How to combine enum, switch and instanceof in Java如何在 Java 中结合 enum、switch 和 instanceof
【发布时间】:2017-01-26 19:09:42
【问题描述】:

我想使用 switch 语句(而不是 else if)来测试三个案例。现在这些案例都测试变量是否是类的实例。我想做这样的事情:

switch(var){

case A: doA();
case B: doB();
case C: doC();

} 

public enum{
A, B, C
}

我希望 A 代表var instanceof A 的情况。有没有办法将此信息分配给枚举中的值?

【问题讨论】:

  • 但是A 已经是一个枚举。我不确定你在问什么。
  • 我不确定程序如何知道案例 A 意味着 var instanceof class A
  • 这不是有效的 Java 代码:枚举类必须有名称。另外,变量var 的类型是什么?如果枚举名为X,即public enum X { A, B, C },并且varX,那么您的代码是完整且有效的,尽管您可能需要添加一些break 语句。
  • Switch on Enum in Java的可能重复
  • 我认为 switch-case 和 if-then-else 语句都不应该在这里使用。如果您想根据对象var 的实际类执行不同的代码,则应该使用方法重载。

标签: java enums switch-statement


【解决方案1】:

如下声明枚举:

private enum ClassType {
    A,
    B,
    C,
    D,
    Unknown;
}

现在,编写一个返回类型的方法:

private ClassType getClassType(Object object){
    ClassType type = null;
    try{
        type = ClassType.valueOf(object.getClass().getSimpleName());
    }catch(IllegalArgumentException e){
        type = ClassType.Unknown;
    }
    return type;
}

现在,将它与 switch 一起使用:

switch(getClassType(object)){
    case ClassType.A:
        //do something
        break;
}

对于新类,您需要在switch 中添加值和大小写。

【讨论】:

    【解决方案2】:

    你首先需要给你的枚举一个名字。

    public enum Day {
        SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
        THURSDAY, FRIDAY, SATURDAY 
    }
    
    public class EnumTest {
    Day day;
    
    public EnumTest(Day day) {
        this.day = day;
    }
    
    public void tellItLikeItIs() {
        switch (day) {
            case MONDAY:
                System.out.println("Mondays are bad.");
                break;
    
            case FRIDAY:
                System.out.println("Fridays are better.");
                break;
    
            case SATURDAY: case SUNDAY:
                System.out.println("Weekends are best.");
                break;
    
            default:
                System.out.println("Midweek days are so-so.");
                break;
        }
    }
    
    public static void main(String[] args) {
        EnumTest firstDay = new EnumTest(Day.MONDAY);
        firstDay.tellItLikeItIs();
        EnumTest thirdDay = new EnumTest(Day.WEDNESDAY);
        thirdDay.tellItLikeItIs();
        EnumTest fifthDay = new EnumTest(Day.FRIDAY);
        fifthDay.tellItLikeItIs();
        EnumTest sixthDay = new EnumTest(Day.SATURDAY);
        sixthDay.tellItLikeItIs();
        EnumTest seventhDay = new EnumTest(Day.SUNDAY);
        seventhDay.tellItLikeItIs();
    }
    }
    

    该示例取自 Java SE 教程页面中的枚举。这正是您的用例。

    https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

    【讨论】:

    • 我在输入答案时不小心提交了答案
    【解决方案3】:

    不确定为什么要使用枚举。从 Java 7 开始,您就可以打开字符串。所以一种选择是

    switch(myObject.getClass().getCanonicalName()) {
      case "java.lang.String" : doA(); break;
      case "com.Acme.foobar" : doB(); break;
      default: throw new IllegalArgumentException();
    }
    

    也就是说,如果类是相关的,并且您可以控制它们,那么@dpr 是正确的:使用多态性和重载可能会更好。

    【讨论】:

    • 因为枚举几乎总是比字符串好。它们是类型安全的,你不能指望它们,等等。
    • @Dave - 100% 同意。但是对于这种特殊情况,类的枚举感觉非常笨拙。 Darshan 的代码工作,但添加的很少,不再是打字错误,感觉像是过度工程,并且随着您添加越来越多的选项,将同样难以维护。
    • 我试试这个,谢谢!我不熟悉方法重载,所以我想这是我解决这个问题的第一站
    • 好的,我现在意识到我的案例不都是instanceof 检查,其中一个是布尔值。如果我这样尝试,似乎我会被卡住。
    【解决方案4】:

    我会使用映射将运行时类型映射到枚举常量,例如:

    public enum ClassType{
        A(Integer.class),
        B(String.class),
        C(Object.class),
        UNKNOWN(null);      
    
        private static final Map<Class<?>, ClassType> typesMap = new HashMap<>();
        public final Class<?> type;
    
        static{
            for (ClassType classType : EnumSet.allOf(ClassType.class)){             
                if(classType.type != null){
                    typesMap.put(classType.type, classType);
                }
            }
        }
    
        private ClassType(Class<?> type){
            this.type = type;           
        }
    
        public static ClassType getClassTypeOf(Class<?> type){
            return typesMap.getOrDefault(type, UNKNOWN);
        }
    }
    

    可以这样使用:

    switch(ClassType.getClassTypeOf(var.getClass())){
        case A:         
            break;
        case B:         
            break;
        case C:
            break;          
        default:            
            break;      
    }
    

    但是,此版本不考虑 var 类型的超类型。要支持超类型查找,您可以将 getClassTypeOf 方法更改为:

    public static ClassType getClassTypeOf(Class<?> type){      
        for(Class<?> lookupType = type; lookupType != null; lookupType = lookupType.getSuperclass()){
            ClassType classType = typesMap.get(lookupType);
            if(classType != null){
                return classType;
            }
        }       
        return UNKNOWN;
    } 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-07-19
      • 2018-02-17
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 2011-11-07
      相关资源
      最近更新 更多