我正在查看Java Generics文档并找到这段代码,
public class WildcardError {
void foo(List<?> l) {
//This give a compile time error
l.set(0,l.get(0));
}
}
Run Code Online (Sandbox Code Playgroud)
我可以理解,我们从a中获取一个元素List<?>并尝试将其设置为另一个元素List<?>.所以编译器会出错.我的问题是,当2个列表不同时,l.set(0, m.get(0))这里列出l并且m不同,这是有道理的.但在上面的例子中,l和l列表相同.为什么编译器不够聪明才能看到它?实施起来难吗?
编辑:我知道我可以通过辅助方法或使用T而不是使用?.来修复它.只是想知道为什么编译器不会为我做这件事.
在您的具体情况下,您可以明确解决此问题:
public class WildcardError {
<T> void foo(List<T> l) {
// This will work
l.set(0, l.get(0));
}
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您不想更改原始API,请引入委托帮助程序方法:
public class WildcardError {
void foo(List<?> l) {
foo0(l);
}
private <T> void foo0(List<T> l) {
// This will work
l.set(0, l.get(0));
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,编译器无法推断出"明显"的<T>类型.我一直在想这个.这似乎可以在编译器中得到改进,因为每张外卡都可以非正式地转换为未知<T>类型.可能有一些原因可以解释为什么这个被省略,也许这只是直觉,但在形式上是不可能的.
更新:
请注意,我刚看到这种特殊的实现Collections.swap():
public static void swap(List<?> list, int i, int j) {
final List l = list;
l.set(i, l.set(j, l.get(i)));
}
Run Code Online (Sandbox Code Playgroud)
JDK家伙采用原始类型,以便在本地处理此问题.这是一个强有力的声明,表明这可能应该由编译器支持,但由于某种原因(例如,没有时间正式指定这一点)只是没有完成
| 归档时间: |
|
| 查看次数: |
5020 次 |
| 最近记录: |