Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collections of generics "Cannot instantiate the type ArrayList<? extends OpDTO> "

Tags:

java

generics

According to what I've read, I think this can't be done, but I'd like to be sure. I have a class OpDTO and several other *DTO extends OpDTO. Then, I want to have a method to extract just certain elements from lists of these child DTOs, and return the extracted elements in another list:

public List<? extends OpDTO> getLastOp (List<? extends OpDTO> listDTOs) {
        List<? extends OpDTO> last = new ArrayList<? extends OpDTO>(); //compile error: Cannot instantiate the type ArrayList<? extends OpDTO>

        //processing

        return last;
    }

I want ult to be a list of elements of the same kind as elements in listDTOs, and use only OpDTO's methods, but it produces a compile error:

Cannot instantiate the type ArrayList<? extends OpDTO>

I also tried doing something like:

public <T> List<T> getLastOp (List<T> listDTOs) {
        List<T> last = new ArrayList<T>();
        //processing

        return last;
    }

But then I can't enforce elements in listDTOs to be a subclass of OpDTO, and can't instantiate T. Any idea?

EDIT

It also occurred to me passing the type as parameter, then I can instantiate it. Would that be ok or is it some kind of bad practice?

private <T extends OpDTO> List<T> getLastOp (List<T> listDTOs, Class<? extends OpDTO> clazz) {
    List<T> ult = new ArrayList<T>();

    //processing
    OpDTO op = clazz.newInstance();
    //processing
    ult.add((T) op);
    op = listDTOs.get(i);

    return ult;
}
like image 438
Luis Sep Avatar asked Dec 06 '22 06:12

Luis Sep


1 Answers

List<? extends OpDTO> is a covariant view of List<T>; that means that any List<T> type can be converted to it, as long as the T matches.
You cannot create an instance of such a type; you can only use it as a variable or parameter type to hold existing instances of concrete generic types.

You need to create a generic method with a constraint that T must inherit your class:

public <T extends OpDTO> List<T> getLastOp (List<T> listDTOs) {
like image 57
SLaks Avatar answered Dec 22 '22 01:12

SLaks