从指定它返回Collection <parenttype> </parenttype> </childtype>的方法返回Collection <childtype>

时间:2013-06-29 19:35:18

标签: java generics collections

我正在尝试编写一个方法,该方法将返回一个集合(例如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{
}

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

1 个答案:

答案 0 :(得分:4)

错误原因
引发异常的原因是Collection<ParentClass>可以包含任何扩展ParentClass的对象。例如,可以向其添加以下类的实例

public class OtherChildClass extends ParentClass{
}

但是因为“真实”集合是Collection<ChildClass>,这会引发错误。或者即使您向其添加了ParentClass,也会引发错误。总的来说还不好。

<强>解决方案
但是,可以通过在类型声明中使用Collection<? extends ParentClass>来解决此问题。这意味着你要返回一个Collection,它被声明为包含一些可以强制转换为ParentClass的类,并被称为 contravariance 。这样的集合不能添加新的对象(允许的null异常)因为编译器永远不能保证你试图放入它的内容是有效的。但是它可以保证从它出来的任何东西都可以转换为ParentClass并且可以这样使用。见here for more details。用法示例如下:

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已被用于简洁,但同样适用于所有集合