为了减少项目中的代码重复,我在泛化某些类时出错,情况如下:
interface ClassRoot{}
public class ClassChild1 implements ClassRoot{
// constructor is omitted for simplicity
public Collection<ClassChild1> createList(){
Collection<ClassChild1> col = getCollectionFromSomewhere();
return col;
}
}
public class Class1{
protected <T extends ClassRoot> Collection<T> doSth(){
Collection<T> myCol = null;
ClassChild1 child = new ClassChild1();
// here I get compile time assignment error
// also (assuming that myCol not null) myCol.add(new ClassChild1());
// is not permitted.
myCol = child.createList();
return myCol;
}
}
这难道不符合多态现象吗?我知道例如,
List<Object> list1;
不能(也不应指定为类型安全)到:
List<String> list2;
但这里我的情况不同,我指定了类型参数来扩展一些特定的类,希望使用oop多态性概念,并正确地执行赋值,实现正确的类。
现在我有两个问题;
有人能解释一下为什么Java中禁止这样做,有什么正当的理由吗?
如何通过使用类型参数或通配符实现这样的功能?
最佳答案
转让
Collection<T> myCol = null;
myCol = child.createList();
将失败,因为您正在将
Collection<ClassChild1>
分配给用未知类型Collection
参数化的T
,该类型可能是ClassChild1
,也可能不是T
。您已经指定了在调用站点推断的
doSth
,因此想象一下下面的代码:Class1 c1;
Collection<ClassChild2> c = c1.doSth();
您可以看到,如果编译器允许您编译这样的
ClassChild1
方法,那么它会把自己画成一个角落,因为在该方法中,您希望向集合中添加一个ClassChild2
实例,在本例中,该集合恰好包含的实例。