Enum.valueOf会针对扩展Enum的未知类型类型发出警告?

时间:2011-08-12 15:26:15

标签: java enums

给这个:

Class<? extends Enum> enumClass = ...; // being passed in from a constructor
Enum e = Enum.valueOf(enumClass, aString); // produces a warning that looks like
  

[未选中]未经检查的方法调用:   java.lang.Enum中的valueOf(java.lang.Class,java.lang.String)是   应用于(java.lang.Class,java.lang.String)

我不想使用泛型,因为这是一个重大变化。我不想压抑。我不明白为什么会发生这种警告。我想这是因为无法扩展Enum类型。我明白了。但我不明白为什么通配符类会抛出这个奇怪的错误。有没有办法在不使用@SupressWarning或使用泛型的情况下解决这个问题?

修改:要澄清,使用泛型的以下代码会使警告消失。

class Foo<T extends Enum<T>>{
    Class<T> enumClass;
    Enum e = Enum.valueOf(enumClass, aString);
}

使用泛型是<T>的用法。我不能这样做,因为这将是一个巨大的层叠变化。

3 个答案:

答案 0 :(得分:4)

EnumClass都是通用的。所以如果你不想要任何警告:

class Foo<T extends Enum<T>>{
    Class<T> enumClass;
    T e = Enum.valueOf(enumClass, str);
}

或者您可以使用通用方法:

public <T extends Enum<T>> T getEnumValue(Class<T> clazz, String name) {
    T e = Enum.valueOf(clazz, name);
    return e;
}

但是如果你不使用泛型,那么你使用的是原始类型,因此编译器会发出警告 - 除了抑制它们之外别无选择。

答案 1 :(得分:2)

这似乎是编译器错误 - 它应该是错误,而不是警告。

在编译方法调用表达式Enum.valueOf(enumClass...)时,首先,将捕获转换应用于参数类型。

<W extends Enum> // a new type parameter 
Class<W> enumClass; // the type of the argument after capture conversion

然后,对Enum.<T>valueOf(enumClass...)进行了类型推断,结果为T=W

然后,检查替换后T的界限,即W是否为Enum<W>的子类型。

(对于15.12.2.2和15.12.2.3,这个过程是相同的; 15.12.2.7肯定会产生T = W)

此处,检查应该失败。所有编译器都知道WEnum的子类型,它不能推断出WEnum<W>的子类型。 (嗯,我们知道这是真的,禁止W=Enum;但是这种知识在子类型规则中不存在,因此编译器不会使用它 - 我们可以通过使用MyEnum层次结构来演示此示例来验证这一点,编译器的行为相同。)

那么为什么编译器仅通过警告传递绑定检查?还有另一条规则允许使用未经检查的警告从RawRaw<X>进行分配。为什么允许这是另一个问题(它不应该是),但编译器确实感觉Raw可赋予Raw<X>。显然这个规则被错误地混合到上面的子类型检查步骤中,编译器认为既然WEnum,它也是某种Enum<W>,编译器只通过一个警告传递子类型检查,违反规范。

如果这样的方法调用不能编译,那么正确的方法是什么?我看不到任何内容 - 只要参数enumClass的类型不在Class<X extends Enum<X>>的递归形式中,任何数量的转换/转换都不能使其成为该形式,因此无法匹配Enum.valueOf方法的签名。也许javac人故意违反规范只是为了让这种代码编译好!

答案 2 :(得分:0)

如果你想想valueOf里面发生了什么,你会发现你的代码不可能像写的那样工作。 Enum.valueOf需要一个实际枚举类的实例作为参数;然后简单地遍历该类的values()寻找匹配。

由于type erasure,泛型不适用于您的代码。没有实际类型传递到Enum.valueOf