作者热门文章
- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在查看 Java Generics documentation并找到了这段代码,
public class WildcardError {
void foo(List<?> l) {
//This give a compile time error
l.set(0,l.get(0));
}
}
我可以理解我们正在从 List<?>
中获取一个元素并尝试将其设置为另一个 List<?>
.所以编译器报错。我的问题是,当两个列表不同时,即 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));
}
}
或者如果你不想改变原有的API,引入一个delegate helper方法:
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>
类型。可能有一些原因导致它被省略,也许这只是直觉,但形式上是不可能的。
更新:
请注意,我刚刚看到了 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 人员求助于原始类型。这是一个强有力的声明,表明编译器可能应该支持它,但由于某些原因(例如,没有时间正式指定它)还没有完成
关于Java 泛型捕获列表<?>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11499989/
我是一名优秀的程序员,十分优秀!