泛型方法中的Java泛型通配符捕获
我正在学习Java泛型,正在阅读Naftalin和Wadler的(非常好的)一本书,我了解到了他所说的在通用方法中捕获通配符,如Collections中的实现。相反:泛型方法中的Java泛型通配符捕获,java,generics,wildcard,Java,Generics,Wildcard,我正在学习Java泛型,正在阅读Naftalin和Wadler的(非常好的)一本书,我了解到了他所说的在通用方法中捕获通配符,如Collections中的实现。相反: public static <T> void reverse(List<T> list){ List<T> temp=new ArrayList<>(list); for(int i=0;i<list.size();i++) list.set(i
public static <T> void reverse(List<T> list){
List<T> temp=new ArrayList<>(list);
for(int i=0;i<list.size();i++)
list.set(i,temp.get(list.size()-1-i));
}
公共静态无效反向(列表){
列表温度=新阵列列表(列表);
for(int i=0;i列表){
2(清单);
}
公共静态作废撤销2(列表){
列表温度=新阵列列表(列表);
对于(int i=0;i,reverse2()
中的T
参数不推断为?扩展对象
,并且不使用通配符?
执行实例化
推理只会发生在调用reverse2()
的方法中。例如,如果调用Collections.emptyList()
,类型参数是什么?在该示例中,类型参数未知,但通常可以在调用站点进行推理:
List<String> empty = Collections.emptyList();
现在,调用该方法的客户端:
final class Test {
public static void main(String... argv) {
List<String> list = Arrays.asList("A", "B", "C");
Reverse.reverse(list);
System.out.println(list);
}
}
重新运行测试
将产生相同的结果,而不是失败
现在更改reverse()
方法的实现,再次只重新编译reverse
类:
static <T extends Integer> void reverse(List<T> list)
static <T extends Integer> void reverse(List<T> list) {
List<T> tmp = new ArrayList<>(list);
for (int i = 0; i < list.size(); ++i) {
T el = tmp.get(list.size() - 1 - i);
list.set(i, el);
}
}
这是因为T
现在实际上被引用了:
T el = tmp.get(list.size() - 1 - i);
在该赋值中,编译器将向类型参数的上限插入一个强制转换,在本例中为Integer
:
T el = (Integer) tmp.get(list.size() - 1 - i);
如果类型T
不受限制(其上限为Object
),则不会执行强制转换,因为它永远不会失败
list
现在被传递到reverse2()
,参数T
被推断为?扩展对象
,[…]
调用reverse2
时,将通配符捕获到一个新的类型变量,该变量不再是通配符。*将T
的类型推断为该捕获类型
类型系统确保我们只能以安全的方式使用此功能
例如,假设我们有一个接受两个列表的方法:
static void swap2(列表1、列表2){
列表温度=新的ArrayList(列表1);
清单1.clear();
列表1.addAll(列表2);
清单2.clear();
列表2.添加所有(临时);
}
如果我们尝试使用通配符捕获调用此函数:
static void swap(List<?> list1, List<?> list2) {
swap2(list1, list2); // <- doesn't compile
}
静态无效交换(列表1、列表2){
swap2(list1,list2);//我看不出这里有什么东西在实例化数组列表
。请将代码片段(以及需要
正确呈现的任何代码文本)用反引号(也称为反勾号`
)。或者,您可以突出显示文本并按{}
按钮。@rgetman done。我在调用方法时传递类型参数。我不明白如何编写方法体传递?作为类型参数。好的,我知道了,那么它是什么?我的意思是,它被推断为什么?好的,我理解一些东西,但我不能诚实地得到所有东西…我不理解它的内部工作原理泛型材料…@erickson静态无效反转(列表)这是给编译时间error@shikhar这只是一段代码。除非它是语法上有效的方法声明的一部分,否则它不会编译。我不知道所有这些捕获通配符的东西,我发现很难理解,因为我刚刚开始学习泛型…我在哪里可以找到易于理解的主题文档ct?可能吧。当然也有。但我所知道的全面、正确、易懂的东西并不多。(我认为StackOverflow更倾向于这样做,但在其知识方面存在一些差距。)特别是捕获的技术推理实际上非常复杂…我只是在阅读了JLS之后才完全理解它,这是非常令人畏惧的。好的,所以我将推迟到以后,当我对该语言的知识成熟时…现在我只想了解我在做什么,以便编写一些像样的代码。谢谢。
static <T extends Integer> void reverse(List<T> list)
static <T extends Integer> void reverse(List<T> list) {
List<T> tmp = new ArrayList<>(list);
for (int i = 0; i < list.size(); ++i) {
T el = tmp.get(list.size() - 1 - i);
list.set(i, el);
}
}
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
T el = tmp.get(list.size() - 1 - i);
T el = (Integer) tmp.get(list.size() - 1 - i);
static <T> void swap2(List<T> list1, List<T> list2) {
List<T> temp = new ArrayList<>(list1);
list1.clear();
list1.addAll(list2);
list2.clear();
list2.addAll(temp);
}
static void swap(List<?> list1, List<?> list2) {
swap2(list1, list2); // <- doesn't compile
}