java难以理解通配符
public static void reverse(List<?> list)
{
List<Object> tmp = new ArrayList<Object>(list);
for (int i = 0; i < list.size(); i++)
{
list.set(i, tmp.get(list.size()-i-1)); // compile-time error , why ?
}
}
我在学仿制药。 我知道:当使用通配符时?将替换为适当的类型。何时调用reverse()方法?将被替换,因为每个类型都是对象的子类型,所以不应该有错误。 我在寻找一个非常清楚的解释。请帮忙
# 1 楼答案
List<?>
是未知类型的列表,我们不知道该列表中的类型,引入了泛型来删除运行时类型转换异常并提供安全性。您无法向包含未定义的集合添加任何类型,因为您将破坏它。例如,如果允许:ClassCastExceptin,因为我们将cat添加到dogs,并将每个dog转换为cat,运行时不存在泛型 所有集合等都包含对象。 这一行将在编译后出现:
对于not allow this,您无法向未知类型集合添加某些内容,并在此处获取编译时错误
list.set(i, tmp.get(list.size()-i-1)); // compile-time error , why ?
# 2 楼答案
Generics work in this way
这里:
因为我们不知道
list
的元素类型代表什么,所以我们不能向它添加对象这里:
在
List
中添加Object
,在绝对值中可以包含不同类型的元素就你而言,情况并非如你所写:
但是编译器不会因为试图理解代码的逻辑而破例
因为否则它应该检查整个代码,编译器错误消息可能会非常复杂
例如,假设您在代码中的某个时间
add tmp.set(0, "aa");
# 3 楼答案
您可以将任何
List<SomeType>
作为List<?> list
参数传递给reverse
方法,编译器应该只允许您将SomeType
的元素添加到List
中例如,它可以是一个
List<String>
,一个List<Ineger>
,等等因此
list.set
无法工作,因为编译器不知道实际的List<?> list
传递给方法支持的元素类型。它不知道List<Object> tmp
的元素来自同一个list
(因此可以安全地添加到其中)编写方法的正确方法是定义泛型类型参数:
现在编译器知道
list
和tmp
都包含相同类型的元素