我试图了解Java Generic的工作原理。这是问题所在。
public static void main(String args[]){
List<Object> obj = Arrays.<Object>asList(23,"456",56.89);
List<Integer> intb = new ArrayList<>();
intb.add(234);
intb.add(345);
Collections.copy(obj,intb);
for(Object d : obj){
System.out.println(d);
}
}
这样可以正常工作。但是我实现了我自己的复制功能
public static <T> void copy(List<? super T> des,List<? extends T> scr){
for(T f : scr){
des.add(f);
}
}
然后我使用copy(obj,intb)而不是Collections.copy(obj,intb)。然后我收到错误。我不明白为什么,但我知道&#34;?扩展T&#34;表示任何类型的T和&#34;的子类型?超级T&#34;指任何类型为T的超类型。
答案 0 :(得分:2)
您无法向此fixed-length list添加任何内容:
List<Object> obj = Arrays.<Object>asList(23,"456",56.89);
您只能为其元素设置新值(这是Collections.copy()
所做的)。另请参阅Javadoc:
返回由指定数组支持的固定大小的列表。
你可能打算这样做:
List<Object> obj = new ArrayList<>(Arrays.asList(23,"456",56.89));
答案 1 :(得分:1)
复制方法
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
int srcSize = src.size();
if (srcSize > dest.size())
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD ||
(src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i<srcSize; i++)
dest.set(i, src.get(i));
} else {
ListIterator<? super T> di=dest.listIterator();
ListIterator<? extends T> si=src.listIterator();
for (int i=0; i<srcSize; i++) {
di.next();
di.set(si.next());
}
}
}
copy将值替换为索引0的索引。
public static <T> void copy(List<? super T> des,List<? extends T> scr){
for(T f : scr){
des.add(f);
}
}
这种方法加入尾巴。
答案 2 :(得分:1)
嗯,有点晚了,但为什么你的编译器抱怨你的代码不仅仅是因为你在List
方法中使用了固定大小(不可变)copy
作为参数。
List<Object> obj = Arrays.<Object>asList(23, "456", 56.89);
Collections.copy(obj, intb);
这也是因为你的(copy
)方法声明。
public static <T> void copy(List<? super T> des,List<? extends T> scr) {
上面的声明有两个带通配符的列表。使用通配符类型<?>
时,会向编译器发出忽略类型信息的消息。无论何时将参数传递给泛型类型,java编译器都会尝试推断传递的参数的类型以及泛型的类型,并证明类型安全性的合理性。现在,(在您的复制方法中)您尝试使用add()
方法在列表中插入元素。由于des(您的目标列表)不知道它所拥有的对象的确切类型,因此向其添加元素是有风险的。在该语言中引入了泛型,以确保首先确保类型安全。所以你不能使用像修改对象的add这样的方法。我希望copy
中java.util.Collections
方法的默认实现有助于澄清它。
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
int srcSize = src.size();
if (srcSize > dest.size())
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD ||
(src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i<srcSize; i++)
dest.set(i, src.get(i));
} else {
ListIterator<? super T> di=dest.listIterator();
ListIterator<? extends T> si=src.listIterator();
for (int i=0; i<srcSize; i++) {
di.next();
di.set(si.next());
}
}
}
我知道已经存在相同的代码块,但没有解释为什么我们不能在add
s上使用带有通配符的List
等方法的原因,那就是主要是为了保护类型安全。