Oxolotl
Oxolotl

Reputation: 443

How to type-safe add element to list whose generic extends class and implements interface?

I'm looking for a type-safe, checked solution to add an element to a list whose generic requires both a class and an interface. The example illustrates what I'd like to do - add an object whose type Cat extends Animal and implements Quadruped to a list List<T> where T extends Animal & Quadruped.

class Example {
    public interface Quadruped { };
    public static class Animal { };
    public static class Cat extends Animal implements Quadruped { };

    public <T extends Animal & Quadruped> List<T> getQuadrupedAnimals(){
        List<T> result = new ArrayList<>();
        Cat cat = new Cat();
        result.add(cat); // compile error
        return result;
    }
}

Of course casting cat to B would resolve the compile error but that would be unchecked.

Is there any solution for this at all? If not, does anyone know the reason why the compiler does not allow this?

Upvotes: 1

Views: 116

Answers (1)

Andy Turner
Andy Turner

Reputation: 140564

does anyone know the reason why the compiler does not allow this?

T is a specific Animal and Quadraped, chosen at the call site of getQuadrupedAnimals().

Legal invocations of that method include:

List<Dog> listOfDogs = getQuadrupedAnimals();
List<Hamster> listOfHamsters = getQuadrupedAnimals();

so you can't put a Cat into that list (nor a Dog nor a Hamster, for that matter), because whatever you put in there might not be castable to the type the caller wants. (You can put literal null in the list, though).

The solution is to declare the return type as List<Cat> (or List<? extends Cat>, or List<? super Cat>), if you want to return a list containing Cats.


An intersection type is only really useful if you use it in a parameter, e.g.

public <T extends Animal & Quadruped> List<T> getQuadrupedAnimals(T animal){
  return List.of(animal);
}

or

public <T extends Animal & Quadruped> int countLegs(List<T> animals){
  return 4 * animals.size();
}

Upvotes: 3

Related Questions