【问题标题】:Java Enums: de-serializing an arbitrary enum from a fileJava Enums:从文件中反序列化任意枚举
【发布时间】:2009-07-30 20:34:35
【问题描述】:

一位同事今天遇到了一个有趣的问题,虽然我认为实际的、宏观的答案是“我们遇到这个问题的事实意味着我们做错了什么”,但我想我会无论如何都要问这个。

鉴于以下情况:

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 时收到以下编译错误:

Bound mismatch: The generic method valueOf(Class&lt;T&gt;, String) of type Enum&lt;E&gt; is not applicable for the arguments (Class&lt;capture#1-of ?&gt;, String). The inferred type capture#1-of ? is not a valid substitute for the bounded parameter &lt;T extends Enum&lt;T&gt;&gt;

所以,我的问题是:是否有可能,仅给定枚举类型名称的 String 表示形式以及其中一个值的 .name(),获取对相应枚举类型对象的引用作为 Enum ?

【问题讨论】:

    标签: java serialization enums


    【解决方案1】:

    编译错误告诉你Class&lt;?&gt;Class&lt;? extends Enum&gt;不一样。试试:

    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)”上收到原始类型警告。

    【讨论】:

    • 嗯...我发誓我试过了;我的演员表中一定没有完全正确的东西。不过效果很好,谢谢!
    • 嗯,我尝试投射到 Class> 但它不起作用。我不会认为原始版本是正确的......
    • 第一个示例中缺少“)”。
    【解决方案2】:

    只需在调用方法之前转换您创建的类, 使其符合方法签名:

    Class<?> c = Class.forName(className);
    Class<? extends Enum> ce = (Class<? extends Enum>)c;
    Enum<?> value1 = Enum.valueOf(ce, enumValue);
    

    现在该类被视为 Enum 的子类。

    备注:

    • 无论如何它在运行时是正确的类,但编译器不知道
    • 为此发明了强制转换:使运行时已知的类型在编译时已知

    【讨论】:

    • 或者根本没有理由... Enum> value1 = Enum.valueOf( ( (Class extends Enum>)Class.forName(className) ), enumValue);
    • 是的,你可以缩短表达式......但我认为作为一个帖子,最好是可读性强 ;-) 在某些情况下,内联转换会变得更加混乱,因为你需要投两次。例如,如果您收到一个您知道仅包含枚举对象的 List,并且您想要调用具有 List 参数的方法。如果我没记错的话,简单地转换它是不可接受的,我需要将它转换为 List> 然后转换为 List
    • Class&amp;lt;? extends Enum&amp;gt; ce = c.asSubclass(Enum.class);怎么样
    猜你喜欢
    • 2013-09-01
    • 1970-01-01
    • 2014-08-10
    • 2022-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-31
    相关资源
    最近更新 更多