我正在看Java 泛型文档并找到了这段代码,
public class WildcardError {
void foo(List<?> l) {
//This give a compile time error
l.set(0,l.get(0));
}
}
我可以理解我们正在从 a 中获取一个元素List<?>
并尝试将其设置为另一个List<?>
。所以编译器会报错。我的问题是,当两个列表不同时,即有意义l.set(0, m.get(0))
这里列出了l
and m
是不同的。但在上面的例子中,l
and l
是相同的列表。为什么编译器不够聪明,看不到这一点?实施起来难吗?
Edit:
我知道我可以通过辅助方法或使用来修复它T
代替?
。只是想知道为什么编译器不为我做这件事。
根据您的具体情况,您可以明确修复此问题:
public class WildcardError {
<T> void foo(List<T> l) {
// This will work
l.set(0, l.get(0));
}
}
或者,如果您不想更改原始 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));
}
}
不幸的是,编译器无法推断出“显而易见”<T>
类型。我也一直想知道这个问题这似乎是编译器中可以改进的东西,因为每个通配符都可以非正式地转换为未知的<T>
类型。也许,有一些原因导致了这一点被省略,也许这只是直觉,但形式上是不可能的。
UPDATE:
注意,我刚刚看到了这个特殊的实现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)));
}
JDK 人员求助于原始类型,以便在本地处理此问题。这是一个强有力的声明,表明这可能should得到编译器的支持,但由于某种原因(例如,缺乏时间正式指定这一点)没有完成
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)