0

我正在尝试编写一个方法,该方法将返回一个集合(例如 Arraylist),该集合使用泛型声明为包含父类或扩展父类的类。对于此方法,集合中的对象将始终用作父类的实例,但在其他上下文中,它们的使用方式不同,因此它们被分开保存。例如:

import java.util.ArrayList;
import java.util.Collection;

public class TestClass {

    public static int PARENTTYPE=0;
    public static int CHILDTYPE=1;

    Collection<ParentClass> parentHolder=new ArrayList<ParentClass>();
    Collection<ChildClass> childHolder=new ArrayList<ChildClass>();

    public TestClass(){

    }

    public Collection<ParentClass> getHolder(int type){
        if (type==PARENTTYPE){
            return parentHolder;
        }else if (type==CHILDTYPE){
            return childHolder; //<--incompatible types
        }else{
            throw new RuntimeException("Not a valid type");
        }
    }

    public static void main(String args[]){
        TestClass test=new TestClass();

        Collection<ParentClass> col1=test.getHolder(PARENTTYPE);
        Collection<ParentClass> col2=test.getHolder(CHILDTYPE);
    }
}


public class ParentClass {
}


public class ChildClass extends ParentClass{
}

但是,我在指示的行收到不兼容的类型异常。如何编写方法,以便可以返回声明为包含扩展某个类的任何对象的集合。

4

1 回答 1

4

Reason for the error
The reason the exception is raised is because Collection<ParentClass> can have any object that extends ParentClass added to it. For example an instance of the following class could be added to it

public class OtherChildClass extends ParentClass{
}

But because the "real" collection is a Collection<ChildClass> this would raise an error. Or even if you added a ParentClass to it it would raise an error. All in all not good.

Solution
This can be solved however by using Collection<? extends ParentClass> in your type declaration. The meaning of this is that you are returning a Collection that is declared as containing some class that could be cast to ParentClass and is called contravariance. Such a collection cannot have new objects added to it (with the admitted exception of null) because the compiler could never guarantee that what you are trying to put into it is valid. But it can guarantee that whatever comes out of it can be cast to ParentClass and used as such. See here for more details. A usage example is as follows:

import java.util.ArrayList;
import java.util.Collection;

public class TestClass {

    public static int PARENTTYPE=0;
    public static int CHILDTYPE=1;

    ArrayList<ParentClass> parentHolder=new ArrayList<ParentClass>();
    ArrayList<ChildClass> childHolder=new ArrayList<ChildClass>();

    public TestClass(){
        parentHolder.add(new ParentClass());
        childHolder.add(new ChildClass());
    }

    public ArrayList<? extends ParentClass> getHolder(int type){
        if (type==PARENTTYPE){
            return parentHolder;
        }else if (type==CHILDTYPE){
            return childHolder; //<-- no longer incompatible types
        }else{
            throw new RuntimeException("Not a valid type");
        }
    }

    public static void main(String args[]){
        TestClass test=new TestClass();

        ArrayList<? extends ParentClass> col1=test.getHolder(PARENTTYPE);
        ArrayList<? extends ParentClass> col2=test.getHolder(CHILDTYPE);

        ParentClass childCastToParent=col2.get(0);

    }
}

N.B. arraylists have been used for brevity but the same applied to all collections

于 2013-06-29T19:35:17.900 回答