Enum.valueOf会针对扩展Enum的未知类型类型发出警告?
给这个:
Class enumClass = ...; // being passed in from a constructor Enum e = Enum.valueOf(enumClass, aString); // produces a warning that looks like
[unchecked] unchecked方法调用:java.lang.Enum中的valueOf(java.lang.Class,java.lang.String)应用于(java.lang.Class,java.lang.String)
我不想使用generics,因为这是一个重大变化。 我不想压抑。 我不明白为什么会发生这种警告。 我想这是因为无法扩展Enum类型。 我明白了。 但我不明白为什么通配符类会抛出这个奇怪的错误。 有没有办法解决这个问题,而不使用@SupressWarning
或使用generics?
编辑 :要澄清,使用generics的以下代码会使警告消失。
class Foo<T extends Enum>{ Class enumClass; Enum e = Enum.valueOf(enumClass, aString); }
的用法就是我使用generics的意思。 我不能这样做,因为这将是一个巨大的层叠变化。
这似乎是一个编译器错误 – 它应该是一个错误,而不是一个警告。
在编译方法调用表达式Enum.valueOf(enumClass...)
,首先,将捕获转换应用于参数类型。
// a new type parameter Class enumClass; // the type of the argument after capture conversion
然后,对Enum.
进行类型推断,结果为T=W
然后,检查替换后T
的界限,即W
是否是Enum
子类型。
(这个过程对于15.12.2.2和15.12.2.3是相同的;而15.12.2.7肯定产生T = W)
在这里,检查应该失败。 所有编译器都知道W
是Enum
的子类型,它不能推断出W
是Enum
的子类型。 (嗯,我们知道这是真的,除非W=Enum
;但这种知识在子类型规则中不存在,因此编译器不使用它 – 我们可以通过使用MyEnum
层次结构来MyEnum
此示例来validation这一点,编译器将表现相同。)
那么为什么编译器仅通过警告传递绑定检查? 还有另一个规则允许使用未经检查的警告从Raw
到Raw
进行分配。 为什么允许这是另一个问题(它不应该是),但编译器确实认为Raw
可以赋给Raw
。 显然这个规则被错误地混合到上面的子类型检查步骤中,编译器认为既然W
是Enum
,它也是一个Enum
,编译器只通过警告传递子类型,违反了规范。
如果这样的方法调用不应该编译,那么正确的方法是什么? 我看不到任何 – 只要参数enumClass
的类型不是已经在Class
的递归forms中,没有任何数量的转换/转换可以使它进入该forms,因此有无法匹配Enum.valueOf
方法的签名。 也许javac家伙故意违反规范只是为了让这种代码编译!
Enum
和Class
都是通用的。 所以如果你不想要任何警告:
class Foo>{ Class enumClass; T e = Enum.valueOf(enumClass, str); }
或者您可以使用通用方法:
public > T getEnumValue(Class clazz, String name) { T e = Enum.valueOf(clazz, name); return e; }
但是如果你不使用generics,那么你使用的是原始类型,因此编译器会发出警告 – 除了抑制它们之外别无选择。
如果你想一想valueOf里面发生了什么,你会发现你的代码不可能像写的那样工作。 Enum.valueOf需要一个实际枚举类的实例作为参数; 然后简单地遍历该类的values()
以寻找匹配。
由于类型擦除 ,generics将无法在您的代码中使用。 没有实际类型传递到Enum.valueOf
。