The issue of variance (particularly contravariance) has got me banging my head against the wall for a week. I have finally understood the theory, thanks to a couple of questions on here, and now as soon as I start working on it, I am getting errors I just don't understand.
I have a simple heirarchy of classes:
abstract class Fruit, Mango extends Fruit, Orange extends Fruit, BloodOrange extends Orange
abstract class Fruit implements PlantEatable {
private boolean isRipe;
private boolean isEatable;
public boolean isRipe() {
return isRipe;
}
public void setRipe(boolean ripe) {
isRipe = ripe;
}
@Override
public boolean isEatable() {
return isEatable;
}
public void setEatable(boolean eatable) {
isEatable = eatable;
}
}
public class Mango extends Fruit {
}
public class Orange extends Fruit{
}
public class BloodOrange extends Orange{
}
Now, The Oracle documentation generally has been great about Generics except for the part that was the most important I find confusing: https://docs.oracle.com/javase/tutorial/java/generics/wildcardGuidelines.html
If I am doing PECS which is Producer Extends Consumer Super
I am trying to do something very simple:
public class UpperBoundEg {
public static <E> void copy(List<? extends E> src, List<? super E> dest) {
src.forEach( item -> {
dest.add(item);
System.out.println("Added to dest: " + item.getClass());
});
}
public static <E> void acceptTest(List<? super Orange> objects) {
}
public static void main(String[] args) {
//Producer
List<? extends Orange> oranges = new ArrayList<>();
//oranges.add(new Orange()); // Doesn't work because its a producer ?
//Consumer
List<? super BloodOrange> objects = new ArrayList<>();
objects.add(new BloodOrange());
//objects.add(new Orange()); // Why doesn't it work ?
//objects.add(new Object()); // Why doesn't it work ?
copy(
Arrays.asList(
new Orange(),
new Orange(),
new BloodOrange(),
new Object(),
new Mango() // Why is this allowed?
),
new ArrayList<>()
);
}
}
Why is this happenning ? I thought List<? super BloodOrange> should take BloodOrange and all its super classes ? Why is it only accepting BloodOrange ?
And Why am I able to add a Mango to the copy function ?