Java泛型&;多态性

Java泛型&;多态性,java,generics,polymorphism,type-parameter,Java,Generics,Polymorphism,Type Parameter,我在泛化某些类以减少项目中的代码重复时出错,情况如下: interface ClassRoot{} public class ClassChild1 implements ClassRoot{ // constructor is omitted for simplicity public Collection<ClassChild1> createList(){ Collection<ClassChild1> col = getColl

我在泛化某些类以减少项目中的代码重复时出错,情况如下:

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;
    }
}
接口类根{}
公共类ClassChild1实现类根{
//为了简单起见,省略了构造函数
公共集合createList(){
Collection col=getcollectionfromwhere();
返回列;
}
}
公共班级1{
受保护的集合doSth(){
集合myCol=null;
ClassChild1 child=新的ClassChild1();
//这里我得到编译时分配错误
//另外(假设mycl不为null)mycl.add(newclasschild1());
//这是不允许的。
mycl=child.createList();
回归霉素;
}
}
这不是反对多态现象吗?我知道比如说,

List<Object> list1;
列表列表1;
永远不能(也不应该被指定为类型安全):

列表列表2;
但这里我的情况不同,我指定了类型参数来扩展一些特定的类,希望利用OOP多态性的概念,并正确地执行赋值来实现正确的类。 现在我有两个问题

  • 有人可以清楚地解释为什么在Java中这是被禁止的,有什么正当的理由吗
  • 如何通过使用类型参数或通配符实现这样的功能
作业

Collection<T> myCol = null;
myCol = child.createList();
您可以看到,如果编译器允许您编译这样一个
doSth
方法,那么它会把自己画成一个角落,因为在该方法中,您希望向一个集合添加一个
ClassChild1
实例,在本例中,该集合恰好包含
ClassChild2
的实例();
Collection<ClassChild1> col = getCollectionFromSomewhere();
return col;
返回列;
正在返回集合,但实际上您的ClassChild1不是集合。这肯定会产生编译时错误。请确保该方法的返回类型必须是集合类型,或者其后代不提供集合,这也是一个错误

不能将
ClassChild1
列表分配给
T
列表


例如,如果您将
RootClass
重命名为
Animal
ClassChild1
重命名为
Cat
。如果现在
T
的一个实例不是
Cat
,您显然无法完成您想要的任务。

很难判断问题是什么,因为:

public ClassChild1 createList(){
一定是错了(正如其他人所指出的)。它是否真的说:

public Collection<ClassChild1> createList(){

还有一个很好的理由——尽管我们不知道集合项上存在什么限制,但这并不意味着没有限制(当你关灯时房间不会消失)。

在这里考虑了你的代码。你的ClassChild实现是

public class ClassChild implements ClassRoot {
    public List<ClassChild> createList() {
        return Arrays.asList(new ClassChild[] {new ClassChild(), new ClassChild()});
    }


}
公共类ClassChild实现类根{
公共列表createList(){
返回Arrays.asList(new ClassChild[]{new ClassChild(),new ClassChild()});
}
}
你的一班是

public class Class1 {

    public static <T extends ClassRoot> Collection<T> doSth(){
        Collection<T> myCol = null;
        ClassChild child = new ClassChild();
        /*you should note here*/
        myCol =  (Collection<T>) child.createList();
        return  myCol;
    }
}
公共类1{
公共静态集合doSth(){
集合myCol=null;
ClassChild=newclasschild();
/*你应该注意这里*/
mycl=(集合)child.createList();
回归霉素;
}
}
你必须停在我提到的“你必须注意这里”的地方。如果您执行强制转换为集合,问题就解决了。但是说到您的问题,您已经创建了一个名为mycl的集合,其中包含扩展类根的类型T。但是createList将返回包含子类型类根的集合的保证是什么呢?因此您始终需要显式强制转换。

createList()应该返回一个集合而不是ClassChild1。是否有编译错误?为清楚起见,您应该在问题中解释错误,而不仅仅是代码注释。已编辑为公共集合createList()。
import java.util.*;

interface ClassRoot {}

class ClassChild1 implements ClassRoot {

    public Collection<? extends ClassRoot> createList(){

        Collection<ClassChild1> col = new ArrayList<ClassChild1>();
        return col;
    }
}

class Class1{
    protected Collection<? extends ClassRoot> doSth(){
        Collection<? extends ClassRoot> myCol = null;
        ClassChild1 child = new ClassChild1();

        myCol = child.createList();
        return myCol;
    }
}
myCol.add(child);
public class ClassChild implements ClassRoot {
    public List<ClassChild> createList() {
        return Arrays.asList(new ClassChild[] {new ClassChild(), new ClassChild()});
    }


}
public class Class1 {

    public static <T extends ClassRoot> Collection<T> doSth(){
        Collection<T> myCol = null;
        ClassChild child = new ClassChild();
        /*you should note here*/
        myCol =  (Collection<T>) child.createList();
        return  myCol;
    }
}