Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
155 views
in Technique[技术] by (71.8m points)

java - Returning a Collection<ChildType> from a method that specifies that it returns Collection<ParentType>

I'm trying to write a method that will return a collection (eg Arraylist) that is declared using generics as containing either a parent class or a class that extends the parent class. For this method the objects in the collection will always be used as instances of the parent class but in other contexts they are used differently hence them being held separately. For example:

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{
}

However I receive an incompatible types exception at the indicated line. How can I write the method such that I can return collections declared as containing any objects that extend a certain class.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...