Generics super vs. extends

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 that if line 1 is uncommented, the following will not compile:

  compound.react(new Organic()); compound.react(new Aliphatic()); compound.react(new Hexane()); 

and if line 2 is ucommented, the following will not compile:

 compound.react(new Organic()); 

In the second example, aliphatic and supertypes are valid. So why is Aliphatics not allowed?

In the first example, why is new Organic not 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) 
+4
source share
4 answers

Your first ad

 Organic<? extends Organic> compound 

means that compound can be Organic<SomeSubtypeOfHexane> (because Aliphatic extends Organic , Hexane extends Aliphatic and SomeSubtypeOfHexane extends Hexane ).

In this case, compound.react(new Organic()) , compound.react(new Aliphatic()) and compound.react(new Hexane()) will result in a type error, since E in compound must be SomeSubtypeOfHexane (or its subtype) .


Your second ad

 Organic<? super Aliphatic> compound 

means compount can be Organic<Aliphatic> .

In this case, compound.react(new Organic()) will result in a type error, since E must be Aliphatic (or its subtype).


Remember that declaring a variable with A<? extends B> A<? extends B> or A<? super B> A<? super B>

  • expands the number of objects that can be assigned to him, and therefore
  • limits what can be done with a variable.

Since the exact type of the class is unknown (only the restriction is known), the compiler should be wrong on the security side and prohibit certain operations that are either not covariant or contravariant. (If you are not already familiar with it, Co- and contravariance is the scientific basis for these types of generics.)

+5
source

The subject is also discussed in several other places, such as:

This is actually a question from a book for preparing a Java certificate from a recent test (question 34). The training book is based on the lesson.

Even with the explanation here and under other links and writing in the book, the solution was incomprehensible to me, because the explanations are mainly based on the List interface and reading that I thought it was some kind of internal specific collection set.

But if you see the definition of the List interface and add the- method on one side and the Organic class with it react on the other side, you will notice that they are defined in a similar way.

 public interface List<E> extends Collection<E> { ... boolean add(E e); ... } public class Organic<E> { ... void react(E e) { } ... } 

Thus, all explanations based on examples of the List interface that you can find anywhere are also valid for this question.

 List<? extends String> list1 = new ArrayList<String>(); List<? super String> list2 = new ArrayList<String>(); list1.add(new String()); //The method add(capture#1-of ? extends String) in the type List<capture#1-of ? extends String> is not applicable for the arguments (String) - // compile-time error list2.add(new Object()); //The method add(capture#2-of ? super String) in the type List<capture#2-of ? super String> is not applicable for the arguments (Object) - // compile-time error 

Take a look at the explanation of this:

+2
source

I think you misunderstood what you set as a parameter to your react() method

Try to change

 void react(E e) { } 

to

 void react(Organic<E> e) { } 

to see the difference. You are looking for objects: Organic<E> Aliphetic<E> Hexane<E>

Not Organic<E> like E

Nor Aliphetic<E> as E

Nor Hexane<E> as E

+1
source

You made some kind of mix.
Organic<E> is Organic<E> in its type.
You cannot perform
new Organic()); You should at least consider the feasibility
new Organic<Object>()); And this is just one compilation error that I can come up with
This, of course, is true for your other instances of objects.

0
source

Source: https://habr.com/ru/post/1442917/


All Articles