【问题标题】:How can I convert from a value to an enum?如何从值转换为枚举?
【发布时间】:2010-10-15 14:13:58
【问题描述】:

我有一个看起来有点像这样的枚举:

public enum Numbers {
  ONE(1), TWO(2), THREE(3);

  public final int num;

  public Numbers(int num) {
    this.num = num;
  }
}

我希望能够从参数转换为枚举,例如从 int 1 转换为枚举 ONE。 Java Enums 中是否有任何内置机制可以做到这一点,还是我必须为此编写自己的逻辑?

【问题讨论】:

    标签: java enums


    【解决方案1】:

    是的,您必须编写自己的逻辑,因为 num 变量是您自己逻辑的一部分:

    public enum Numbers {
        ONE(1), TWO(2), THREE(3);
    
        public final int num;
    
        private Numbers(int num) {
            this.num = num;
        }
    
        public static Numbers getNumber(int i){
            for(Numbers number : Numbers.values()){
                if(i == number.num){
                    return number;
                }
            }
            throw new IllegalArgumentException("This number doesn't exist");
        }
    }
    

    【讨论】:

    • 这支持一个比我的答案更普遍的问题(基本上,无论你喜欢什么索引系统),但有一些性能权衡:每次查找调用增量搜索匹配值,索引内存,以及iirc 在每次查找调用时创建 values() 数组。
    • @Carl,是的,我想一个解决方案是在i 和基于switch 值的return 上有一个switch 语句。我会快很多。但还是那么丑。
    • 另外,如果您打算这样做,为什么不直接使用 Map<Integer,Number>,在其中静态创建地图?
    • @Carl,正如我所说,我在之前的评论中找到了解决方案,这越来越难看:P
    【解决方案2】:

    如果你想从序数转换,你必须自己做。但是,枚举名称会自动转换。顺便说一句,不需要指定序数,这是自动完成的,它从 0 开始,并且有一个 ordinal() getter。

    Enum.valueOf(Numbers.class, "ONE")
    

    将返回 Numbers.ONE

    【讨论】:

    • 为什么不Numbers.valueOf("ONE")
    • @user102008 - 不太清楚我写的时候在想什么 :)
    【解决方案3】:

    如果您可以改为使用 ZERO 开始您的特定枚举,您可以这样做

    // ...
    private static final Numbers[] list = values();
    public static Numbers get(int which) { return list[i]; }
    // ...
    

    并忽略为您的枚举分配索引。

    编辑:重构安全选项:

    //..
    private static final Map<Integer, Numbers> getter; static {
     Numbers[] ns = values();
     getter = new HashMap<Integer, Numbers>(ns.length, 1f);
     for (Numbers n : ns) getter.put(n.num, n);
    }
    public static Numbers get(int which) { return getter.get(which); }
    //..
    

    这也有利于将您的索引更改为您喜欢的任何类型并返回 null 而不是在您要求垃圾时抛出异常(这可能更可取)。

    【讨论】:

    • 这不是一个好主意,因为除了有点脆弱之外,它还依赖于枚举常量的 ordinal 值,这与 @987654324 无关@ 场地。如果将枚举定义为public enum Numbers { THREE(3), TWO(2), ONE(1), ZERO(0) },这是完全合法的,那么您的代码将返回错误的值。
    • @Andrzej:它确实依赖于这个事实,是的,依赖它是脆弱的。但如果问题足够简单(完全判断调用),额外的灵活性可能不值得更灵活的解决方案的性能损失。
    • 我会接受(可能是微不足道的)性能损失,而不是在“安全”重构期间中断的代码,任何一天。如果提高性能是推荐这种方法的唯一原因,那么 Knuth 有话要对您说。
    • @Andrzej:比性能更重要,与重构安全选项相比,我的第一个答案很容易实现(我想说是微不足道的)。我会在第一遍中使用它,并注意一个简短的“TODO:实现重构安全选项”,如果出现非平凡的重构。是的,我可能最终会重复工作,但如果问题真的很简单并且我从不重构,我会花费更少的时间并获得更好的性能。比如...惰性实例化,仅用于设计。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 2017-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    相关资源
    最近更新 更多