Saher Ahwal Saher Ahwal - 1 month ago 15
Java Question

Java Generics WildCard Question: List<? extends A>

Let's say I have these classes : Vehicle, Car and Spaceship:

class Vehicle{

void rideVehicle(Vehicle v){
System.out.println("I am riding a vehicle!");
}

}

class Car extends Vehicle{
void rideVehicle(Vehicle c){
System.out.println("I am riding a car!");
}
}


class SpaceShip extends Vehicle{
void rideVehicle(Vehicle c){
System.out.println("I am riding a spaceship!");
}

}


and I write this method addCars:

private static void addCars(List<? extends Vehicle> vcls){
vcls.add(new Car());
vcls.add(new Car());
vcls.add(new Car());

}


Why do I get a compile time error?? I understand that List is a supertype of List for any X that extends Vehicle. right?

Thanks

Edit: the error I get (compile-time) : The method add(capture#2-of ? extends Vehicle) in the type List is not applicable for the arguments (Car).

Answer

Method arguments are contravariant in the subtype, and by the definition of the wildcard, for every type T that extends Vehicle Foo<T> is a subtype of Foo<* extends Vehicle>. The implication of this is that wildcards are great when you only care about the return type, but dont work in situations like this when you want to pass a value of the type to a method.

The problem is that a user might try to call

List<SpaceShip> l = ...
addCars(l);

if your code were to compile, l would then be a list of spaceships containing 3 cars. Clearly no good.