Home > database >  Correct Generics using for List
Correct Generics using for List

Time:02-24

I have the next code:

class Cat extends Animal{}

List<Cat> oldCats = getCats();
List<Cat> newCats = doSomeWork(oldCats);

public static List<? extends Animal> doSomeWork(List<? extends Animal> animals){
    List<? extends Animal> newAnimals = new ArrayList<>();
    for(Animal a : animals){
        newAnimals.add(a);
    }
    return newAnimals;
}

I have compilation error, that required type is not correct.

Required type:List<Cat>
Provided:List<capture of ? extends Animal>

How properly tune generics for List?

CodePudding user response:

public static List<? extends Animal> doSomeWork(List<? extends Animal> animals){
  List<? extends Animal> newAnimals = new ArrayList<>();

Every time you use a ? extends Animal, it means a different type of "something that is a subclass of Animal". So, the type of the parameter, the type of the return value and the type of the local variable are different: you can't add things from animals into newAnimals (or vice versa), and you can't return either animals or newAnimals from the method.

Also, that return type isn't "List of a particular type of animal", it's "List of a particular but unknown type of animal". You can't get a List<Cat> back from that, you can only ever get a List<? extends Animal>.

If you want to indicate that they are the same, you need to declare a type variable, which you use in all of the declarations.

public static <T extends Animal> List<T> doSomeWork(List<T> animals){
  List<T> newAnimals = new ArrayList<>();

This is still "some subclass of Animal", but the fact they are all referred to by the T means these are the same subclass; and the type that is returned is the same as the type you passed in.

CodePudding user response:

It looks like you want

public static <T extends Animal> List<T> doSomeWork(List<T> animals){
    List<T> newAnimals = new ArrayList<>();
    return newAnimals;
}

CodePudding user response:

Did it in such way:

public static <T extends Animal> List<T> doSomeWork(List<T> animals){
    List<T> newAnimals = new ArrayList<>();
    for (T a : animals){
        Animal castedAnimal = (Animal)a;
        newAnimals.add(a);
    }
    return newAnimals;
}

I don't like this casting... But it works

  • Related