【问题标题】:Compare Java enum values比较 Java 枚举值
【发布时间】:2009-07-19 11:09:57
【问题描述】:

有没有办法检查一个枚举值是否“大于/等于”另一个值?

我想检查错误级别是否为“错误或以上”。

【问题讨论】:

    标签: java enums


    【解决方案1】:

    所有 Java 枚举都实现 Comparable:http://java.sun.com/javase/6/docs/api/java/lang/Enum.html

    你也可以用ordinal的方法把它们变成ints,那么比较就很简单了。

    if (ErrorLevel.ERROR.compareTo(someOtherLevel) <= 0) {
      ...
    }
    

    【讨论】:

    • 显然,它并不是真正的枚举。但它有一个方法'isGreaterOrEqual()'
    • @ripper234:你的问题是“枚举”
    • docs.oracle.com/javase/7/docs/api/java/lang/… 带回家的消息是:“此方法实现的自然顺序是声明常量的顺序”。因此 enum { TRACE, DEBUG, INFO, WARN } 表示:TRACE
    【解决方案2】:

    一个更具表现力的版本是

    myError.isErrorOrAbove(otherError)
    

    myError.isWorseThan(otherError)
    

    通过这种方式,您可以在 Enum 内部定义排序,并且可以根据需要在内部更改实现。现在 Enum 的客户端可以在不知道任何细节的情况下比较值。

    一个可能的实现应该是

    public enum ErrorLevel {
    
        INFO(0),
        WARN(1),
        ERROR(2),
        FATAL(3);
    
        private Integer severity;
    
        ErrorLevel(int severity) {
            this.severity = severity;
        }
    
        public boolean isWorseThan(ErrorLevel other) {
            return this.severity > other.severity;
        }
    }
    

    我也不建议使用 ordinal() 方法进行比较,因为当有人更改 Enum 值定义的顺序时,您可能会得到意外的行为。

    【讨论】:

    • 同意。依赖序数位置是一个巨大的错误,可能会导致一些非常难以追踪的错误。
    【解决方案3】:

    Java enum 已经内置了compareTo(..) 方法,它使用枚举位置(又名序数)来比较一个对象和另一个对象。位置是根据声明 enum 常量的顺序确定的 ,其中第一个常数的序数为零。
    如果这种安排不合适,您可能需要通过添加内部字段来定义自己的比较器,如下所示:

    import java.util.Comparator;
    
    public enum Day {
      MONDAY(1, 3),
      TUESDAY(2, 6),
      WEDNESDAY(3, 5),
      THURSDAY(4, 4),
      FRIDAY(5, 2),
      SATURDAY(6, 1),
      SUNDAY(0, 0);
    
      private final int calendarPosition;
      private final int workLevel;
    
      Day(int position, int level) {
        calendarPosition = position;
        workLevel = level;
      }
    
      int getCalendarPosition(){ return calendarPosition; }  
      int getWorkLevel() { return workLevel;  }
    
      public static Comparator<Day> calendarPositionComparator = new Comparator<Day>() {
        public int compare(Day d1, Day d2) {
          return d1.getCalendarPosition() - d2.getCalendarPosition();
        }
      };
    
      public static Comparator<Day> workLevelComparator = new Comparator<Day>() {
        public int compare(Day d1, Day d2) {
          // descending order, harder first
          return d2.getWorkLevel() - d1.getWorkLevel();
        }
      };        
    }
    

    驱动检查是否一切正常:

    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    
    public class EnumTest
    {
      public static void main (String[] args) {
         List<Day> allDays = Arrays.asList(Day.values());
         System.out.println("===\nListing days in order of calendar position:");
         Collections.sort(allDays, Day.calendarPositionComparator);
         showItems(allDays);
         System.out.println("===\nListing days in order of work level:");
         Collections.sort(allDays, Day.workLevelComparator);
         showItems(allDays);
      }
    
      public static void showItems(List<Day> days) {
        for (Day day : days) {
          System.out.println(day.name());
        }
      }
    }
    

    【讨论】:

    • 默认实现将其标记为最终版本太可怕了。我的意思是如果有人因为看起来更漂亮而重新排列枚举顺序,那么你的整个行为可能会改变。
    • @mjs 这就是为什么我建议不要使用 Enum 序数,而是使用值作为构造函数参数。
    • 是的,我也选择了。
    【解决方案4】:

    假设您已按严重性顺序定义它们,您可以比较每个值的序数。序数是它在枚举声明中的位置,其中初始常量的序数为零。

    通过调用值的 ordinal() 方法获取序数。

    【讨论】:

    • 默认实现将其标记为最终版本太可怕了。我的意思是如果有人因为看起来更漂亮而重新排列枚举顺序,那么你的整个行为可能会改变
    【解决方案5】:

    我想检查错误级别是否为“错误或以上”。

    这样的枚举应该有一个与之关联的级别。因此,要找到等于或更大的值,您应该比较级别。

    使用序数依赖于枚举值出现的顺序。如果你依赖它,你应该记录它,否则这种依赖会导致脆弱的代码。

    【讨论】:

      【解决方案6】:

      另一种选择是

      enum Blah {
       A(false), B(false), C(true);
       private final boolean isError;
       Blah(boolean isErr) {isError = isErr;}
       public boolean isError() { return isError; }
      }
      

      根据您的问题,我假设您使用枚举来指定某种返回值,其中一些是错误状态。此实现的优点是不必在特定位置添加新的返回类型(然后调整您的测试值),但缺点是在初始化枚举时需要一些额外的工作。

      进一步追寻我的假设,错误代码对用户有用吗?调试工具?如果是后者,我发现异常处理系统对于 Java 来说还不错。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-14
        • 1970-01-01
        • 1970-01-01
        • 2010-12-17
        相关资源
        最近更新 更多