Old*_*eon 19 java generics java-8
我意识到Java 8仍然处于测试阶段,但这个让我感到奇怪:
public class Fields<C extends Enum<C>> {
public Fields(Set<C> columns) {
// A sample column used to find the universe of the enum of Columns.
C sampleCol = columns.iterator().next();
// Java 8 needs a cast here.
Set<C> allColumns = EnumSet.allOf((/*Class<C>)*/ sampleCol.getClass());
// ... there's more to this that I've deleted.
}
}
Run Code Online (Sandbox Code Playgroud)
错误如下:
error: incompatible types: inferred type does not conform to equality constraint(s)
Set<C> allColumns = EnumSet.allOf(sampleCol.getClass());
inferred: C
equality constraints(s): C,CAP#1
where C is a type-variable:
C extends Enum<C> declared in class Test.Fields
where CAP#1 is a fresh type-variable:
CAP#1 extends Enum from capture of ? extends Enum
Run Code Online (Sandbox Code Playgroud)
这是Java 8的错误还是新功能?
Pau*_*ora 18
有趣的是,这是原始类型处理的微妙变化.
首先,让我们澄清你的例子.返回类型Object.getClass
是特殊的:
实际结果的类型是
Class<? extends |X|>
其中|X|
是静态类型上其表达的擦除getClass
被调用.
在这种情况下,X
将是类型参数C
,其擦除到Enum
.所以sampleCol.getClass()
回报Class<? extends Enum>
.EnumSet.allOf
声明type参数E extends Enum<E>
,并在您的情况下? extends Enum
被推断为其类型参数.
重要的是这Enum
是一种原始类型.原始类型的使用已被视为删除看似无关的泛型,例如在这篇文章中:为什么这个通用的Java代码不能编译?在他的答案,乔恩斯基特援引JLS§4.8("原始类型")来弥补这一直观行为.
在使用Java 7的示例中似乎发生了类似的行为:EnumSet.allOf(sampleCol.getClass())
允许使用"未经检查的调用"警告进行编译(这会被后续的"未经检查的转换"警告隐藏,从而将生成的原始内容分配EnumSet
给Set<C>
).
问题变成:在通用通配符的边界中出现原始类型是否允许未经检查的转换?JLS§4.8没有提到这一点,因此它含糊不清.可能这是一个错误,但似乎合理收紧了这种行为.虽然标准的原始类型Enum
本身可能是传统API所期望的,但是"半生不熟"类型Class<? extends Enum>
只能在泛型后发生,因此让它破坏泛型类型检查并没有多大意义.
无论如何,我有兴趣看看是否有人可以指出有关此更改的文档 - 我的搜索没有改变任何东西.
关于您的特定代码:您应该使用getDeclaringClass()
.编译器无法知道调用getClass
a C
将完全返回Class<C>
; 实际上,如果在具有常量特定类的枚举上使用它,则不会.这正是Enum
声明该方法的用例.
归档时间: |
|
查看次数: |
2531 次 |
最近记录: |