Just when I thought I finally understood generics, I came across the following example:
public class Organic<E> {
void react(E e) { }
static void main(String[] args) {
//1: Organic<? extends Organic> compound = new Aliphatic<Organic>();
//2: Organic<? super Aliphatic> compound = new Aliphatic<Organic>();
compound.react(new Organic());
compound.react(new Aliphatic());
compound.react(new Hexane());
} }
class Aliphatic<F> extends Organic<F> { }
class Hexane<G> extends Aliphatic<G> { }
It says, if line 1 is uncommented, the following will not compile:
compound.react(new Organic());
compound.react(new Aliphatic());
compound.react(new Hexane());
while if line 2 is ucommented, the following will not compile:
compound.react(new Organic());
In the second example, Aliphatic and it's supertypes are allowed. So why isn't Aliphatic allowed?
In the first example, why isn't new Organic
allowed??
1st compiler error:
- The method react(capture#1-of ? extends Organic) in the type Organic<capture#1-of ? extends Organic> is not applicable for the arguments (Organic)
- The method react(capture#2-of ? extends Organic) in the type Organic<capture#2-of ? extends Organic> is not applicable for the arguments (Aliphatic)
- The method react(capture#3-of ? extends Organic) in the type Organic<capture#3-of ? extends Organic> is not applicable for the arguments (Hexane)
2nd compiler error:
- The method react(capture#1-of ? super Aliphatic) in the type Organic<capture#1-of ? super Aliphatic> is not applicable for the arguments (Organic)
Your first declaration
Organic<? extends Organic> compound
means that compound
could be an Organic<SomeSubtypeOfHexane>
(since Aliphatic
extends Organic
, Hexane
extends Aliphatic
and SomeSubtypeOfHexane
extends Hexane
).
In that case, compound.react(new Organic())
, compound.react(new Aliphatic())
and compound.react(new Hexane())
would lead to a type error, since E
in compound
must be a SomeSubtypeOfHexane
(or subtype thereof).
Your second declaration
Organic<? super Aliphatic> compound
means that compount
could be an Organic<Aliphatic>
.
In that case compound.react(new Organic())
would lead to a type error, since E
must be an Aliphatic
(or subtype thereof).
Remember that declaring a variable using A<? extends B>
or A<? super B>
Since the exact type of the class is unknown (only a constraint is known), the compiler has to err on the side of safety and disallow certain operations that are either not co- or contravariant. (If you are not already familiar with it, Co- and contravariance is the scientific background of these types of generics.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With