And*_*ips 13 java generics java-7
以下代码
class GenericCompilationFailureDemo {
List<? extends GenericCompilationFailureDemo> newList() {
return new ArrayList<GenericCompilationFailureDemo>();
};
void useList() {
List<GenericCompilationFailureDemo> list =
(List<GenericCompilationFailureDemo>) newList();
}
List<? extends Set<GenericCompilationFailureDemo>> newListOfSpecificSets() {
return new ArrayList<Set<GenericCompilationFailureDemo>>();
};
void useListOfSpecificSets() {
List<Set<GenericCompilationFailureDemo>> listOfSpecificSets =
(List<Set<GenericCompilationFailureDemo>>) newListOfSpecificSets();
}
List<? extends Set<? extends GenericCompilationFailureDemo>> newListOfSets() {
return new ArrayList<Set<? extends GenericCompilationFailureDemo>>();
};
void useListOfSet() {
List<Set<? extends GenericCompilationFailureDemo>> listOfSets =
(List<Set<? extends GenericCompilationFailureDemo>>) newListOfSets();
}
}
Run Code Online (Sandbox Code Playgroud)
在Sun JDK 1.6.0_20下编译(在Windows Vista上为64位,但我认为没有任何区别)但在Oracle JDK 1.7.0_01(同一平台)下导致以下编译失败:
[ERROR] src\main\java\GenericCompilationFailureDemo.java:[56,78] error: inconvertible types
Run Code Online (Sandbox Code Playgroud)
请注意,前两个 "扩展到特定类型"转换useList并且useListOfSpecificSets两者仍然在1.7.0_01下成功,所以它似乎与"双通用扩展"有关.
任何想法可能在6到7之间发生了变化,观察到的行为是否符合规范或错误?
编辑以回应Sanjay的评论:
@Sanjay:啊哈,有意思!这里的输出来自java -version:
java version "1.7.0_01"
Java(TM) SE Runtime Environment (build 1.7.0_01-b08)
Java HotSpot(TM) 64-Bit Server VM (build 21.1-b02, mixed mode)
Run Code Online (Sandbox Code Playgroud)
这里的结果javac GenericCompilationFailureDemo.java(与上面相同的代码,包含List,ArrayList和Set的import语句):
GenericCompilationFailureDemo.java:30: error: inconvertible types
(List<Set<? extends GenericCompilationFailureDemo>>) newListOfSets()
;
^
required: List<Set<? extends GenericCompilationFailureDemo>>
found: List<CAP#1>
where CAP#1 is a fresh type-variable:
CAP#1 extends Set<? extends GenericCompilationFailureDemo> from capture of ?
extends Set<? extends GenericCompilationFailureDemo>
Note: GenericCompilationFailureDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
Run Code Online (Sandbox Code Playgroud)
这显然是一个javac7错误.应该允许每个铸造转换规则[1]
其中一条规则允许缩小参考转换...然后是未经检查的转换
List<A> => List<B>此规则允许投射
List<A> => List // narrowing reference conversion
List => List<B> // unchecked conversion
Run Code Online (Sandbox Code Playgroud)
但这不是故事的全部; 规范有进一步的规则禁止铸造List<String>=>List<Integer>,因为它们是可证明的不同的参数化类型.没有同时属于这两种类型的对象,因此编译器认为最好不要禁止这种明显的编程错误.(你可以明确地绕过它List<String>=>List=>List<Integer>)
最后一条规则不适用于此; 所以它看起来像一个javac7错误.
为什么最后的规则不适用:所以我们正在铸造List<? extends A>到List<A>.这里捕获转换应用于List<? extends A>[2]所以我们实际上是转换List<T>为List<A>,其中T是一个带有上限的新类型变量A.
现在的问题是,是否List<T>和List<A>有可证明不同的参数化类型.我的理解是它是假的(你的前两个例子编译时必须是假的).由于T是一个类型变量,它可以取值List<T>和List<A>相同的参数化类型(即何时T=A).这种推理应适用于任何类型A.
[1] http://java.sun.com/docs/books/jls/third_edition/html/conversions.html#5.5
[2] http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#341306
| 归档时间: |
|
| 查看次数: |
3575 次 |
| 最近记录: |