Java枚举:从文件反序列化任意枚举类型

4

今天我的同事遇到了一个有趣的问题,虽然我认为实际上的大局答案是“我们遇到这个问题说明我们做错了什么”,但我还是想问一下。

以下是给定的内容:

public class CrazyEnumTest {

  public class EnumeratedThing<T extends Enum<T>> {
    public T myValue;

    public EnumeratedThing(T value) {
      myValue = value;
    }
  }

  public static void main (String[] args) {
    String className = args[0];
    String enumValue = args[1];

    Enum<?> value1 = Enum.valueOf(Class.forName(className), enumValue);
    EnumeratedThing<?> thing1 = new EnumeratedThing(value1);
  }
}

我在调用Enum.valueOf时遇到了以下编译错误:
绑定不匹配:类型为Enum的泛型方法valueOf(Class, String)对参数(Class, String)不适用。捕获类型capture#1-of ?不是>的有限制的参数的有效替代。
因此,我的问题是:是否可能仅凭枚举类型名称的字符串表示以及其中一个值的.name(),作为Enum对象,获取对应的枚举类型对象的引用?
2个回答

9
编译错误提示您,Class<?>Class<? extends Enum>不相同。请尝试:
Enum<?> value1 =
        Enum.valueOf((Class<? extends Enum>) Class.forName(className), enumValue);

请注意,您将收到一个未经检查的强制类型转换警告,请确保 className 确实代表一个枚举。您可以通过在 Class 对象上调用 isEnum() 方法来进行检查,如下所示:
Class<?> enumClass = Class.forName(className);
if (enumClass.isEnum()) {
    @SuppressWarnings("unchecked") // we just checked it, so it had better work
    Enum<?> value1 = Enum.valueOf((Class<? extends Enum>) enumClass, enumValue);
    EnumeratedThing<?> thing1 = new EnumeratedThing(value1);
}

当然,无论如何,在“new EnumeratedThing(value1)”上都会得到一个原始类型警告。

1
嗯...我本以为我试过了那个;可能我的类型转换没有做对。不过那个方法很好用,谢谢! - Sbodd
1
嗯,我尝试将其转换为Class <? extends Enum <?>>,但不起作用。我本不认为原始版本是正确的... - thSoft
你在第一个例子中缺少一个")"。 - WhyNotHugo

1
在调用方法之前,只需将您创建的类转换为与方法签名相符的形式即可:
Class<?> c = Class.forName(className);
Class<? extends Enum> ce = (Class<? extends Enum>)c;
Enum<?> value1 = Enum.valueOf(ce, enumValue);

现在这个类被视为枚举的子类。

备注:

  • 无论如何,在运行时它都是正确的类,但编译器不知道
  • 强制转换就是为了解决这个问题:使运行时已知类型在编译时也能被知晓

枚举<?> value1 = Enum.valueOf(((Class<? extends Enum>) Class.forName(className)), enumValue);或者无缘无故... - Tom Neyland
是的,你可以缩短表达式……但我认为作为一篇文章,更好的阅读体验更重要;-) 在某些情况下,内联转换会变得更加混乱,因为您需要进行两次转换。例如,如果您收到一个包含仅枚举对象的List<I>,并且您想调用具有List<Enum>参数的方法。如果我没记错的话,简单地进行强制转换是不可接受的,我需要将其转换为List<?>,然后再转换为List<Enum>。 - KLE
Class&lt;? extends Enum&gt; ce = c.asSubclass(Enum.class); 这段代码如何? - newacct

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接