Quite simply, if you have an object of some general type with a parameter of type T created using a template ? extends X ? extends X , then you cannot call object methods that accept parameters of type T , because the compiler cannot guarantee type safety. However, you can call methods that return T (and assign the return value to a variable of type X ). In your specific example, it looks like it should be safe
Organic<? extends Organic> compound = new Aliphatic<Organic>(); compound.react(new Organic());
but remember that the compiler must match the react call based on the declaration type ( ? extends Organic ), it cannot rely on what you assigned to RHS. If the compiler allowed this, then it would also have to be allowed
Organic<? extends Organic> compound = new Aliphatic<Hexane<?>>(); compound.react(new Organic());
which is clearly wrong - this is exactly the same situation as
Collection<? extends Number> nums = new ArrayList<Float>(); nums.add(Integer.valueOf(1));
(all this aside from the fact that, since Organic is common, you need to say Organic<? extends Organic<?>> or the like, and not just Organic<? extends Organic> )
source share