【问题标题】:How to create generic enum converter?如何创建通用枚举转换器?
【发布时间】:2015-01-26 09:18:40
【问题描述】:

我想写一个可以像new EnumConverter(MyEnum.class);这样使用的泛型类

但是我必须编写那个类,以便它与对enum.values() 的通用调用一起工作?

public class EnumConverter {
    public EnumConverter(Class<Enum<?>> type) {
        this.type = type;
    }

    public EnumConverter convert(String text) {
        //error: Type mismatch: cannot convert from element type capture#1-of ? to Enum<?>
        for (Enum<?> candidate : type.getDeclaringClass().getEnumConstants()) {
            if (candidate.name().equalsIgnoreCase(text)) {
                return candidate;
            }
        }
    }
}

【问题讨论】:

  • this.type是什么类型;它是如何声明的?
  • 您的转换方法有问题,因为它应该返回 EnumConvertercandidate 的类型是 Enum&lt;?&gt; !!
  • 我认为是构造函数
  • 我绝对不清楚问题是什么。
  • 好问题。这是相关的,但不同:stackoverflow.com/questions/4014117/…(请不要将此评论视为“嘿,这个问题是骗子!”)

标签: java generics enums


【解决方案1】:

您的问题不一致且代码无效: 1) this.type 未定义为字段 2)你定义转换返回EnumConverter但返回Enum

要从文本中返回枚举的枚举值,您不需要通用的东西。你只需使用:

Enum.valueOf(MyEnum.class, "TWO")

【讨论】:

    【解决方案2】:

    您的方法 convert 的返回类型是错误的:应该是 Enum 而不是 EnumConverter。然后你不必调用getDeclaringClass(),而是使用你已经输入的Class

    我会建议一种更通用的方法:

    public static class EnumConverter<T extends Enum<T>>
    {
    
        Class<T> type;
    
        public EnumConverter(Class<T> type)
        {
            this.type = type;
        }
    
        public Enum<T> convert(String text)
        {
            for (Enum<T> candidate : type.getEnumConstants()) {
                if (candidate.name().equalsIgnoreCase(text)) {
                    return candidate;
                }
            }
    
            return null;
        }
    }
    

    【讨论】:

    • 这可能就是我要找的东西。但这不能进一步优化吗,因为我必须同时提供类型参数作为通用参数和构造函数参数,如new EnumConverter(MyEnum.class);new EnumConverter&lt;MyEnum&gt;();
    • 为什么使用这个类和使用Enum.valueOf((Class&lt;T&gt; enumType, String name)有什么不同?
    • 我在写这个答案时不知道 Enum.valueOf() 方法,只是想展示如何让他的方法发挥作用。也许您可以使用它来跟踪转换;-)
    • @membersound 它可以通过在通用静态方法中进行转换来进一步优化。但是你可以直接使用 Enum.valueOf()。
    【解决方案3】:

    Following 不是请求的类,但仍然比其他一些答案有所改进,因为它不会产生警告 (java 11/IDEA 2020)

        static <Dest extends Enum<Dest>> Dest
        convertEnumStrict(final Class<Dest> destinationClassType, final Enum<?> sourceEnum) {
            if (sourceEnum == null) {
                return null;
            }
            return Dest.valueOf(destinationClassType, sourceEnum.name());
        }
    
        static <Dest extends Enum<Dest>> Dest
        convertEnumOrNull(final Class<Dest> destinationClassType, final Enum<?> sourceEnum) {
            try {
                return convertEnumStrict(destinationClassType, sourceEnum);
            } catch (IllegalArgumentException e) {
                return null;
            }
        }
    

    【讨论】:

      【解决方案4】:

      将两个最佳答案放在一起,您会得到一个干净的衬里:

      public <T extends Enum<T>> T getEnumValue(Class<T> type, String str) {
          return Enum.valueOf(type, str);
      }
      

      【讨论】:

      • 如果在编译时类型未知,有没有办法使用它?例如Class&lt;?&gt; type
      【解决方案5】:

      如果有人正在寻找没有 for 循环的替代解决方案。

         // classType is target Enum
           public static Enum<?> toEnum(final Class<? extends Enum> classType, final Enum<?> enumObj) {
                  if (enumObj == null) {
                      return null;
                  } else {
                      return enumObj.valueOf(classType, enumObj + "");
                  }
      

      用法:

       TestEnum1 enum1 = (TestEnum1) toEnum(TestEnum1.class, TestEnum1.HELLO_ENUM);
      

      【讨论】:

        猜你喜欢
        • 2019-06-21
        • 2019-02-11
        • 2018-04-18
        • 2013-06-02
        • 1970-01-01
        • 2013-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多