Yet another novice, trying to comprehend Java Generics. I've observed all topics, I found, but I still have huge questions. Could you please explain me the following things:
<? extends SomeClass>
means, that?
is "any type", andextends SomeClass
means, that this any type can be only a subclass ofSomeClass
. OK, I write two elementary classes:
abstract class Person {
private String name;
public Person(String name) {
this.name = name;
}
}
class Student extends Person {
public Student(String name) {
super(name);
}
}
Class Student
will be ?
in our example. ? extends Person
, to be precise.
Then I'm trying to add new student to ArrayList, that, as I understand from written above, applies all classes, that are subclasses of Person:
Student clarissa = new Student("Clarissa Starling");
List<? extends Person> list = new ArrayList<>();
list.add(clarissa); //Does not compile
Eclipse says:
"The method add(capture#3-of ? extends Person) in the type List is not applicable for the arguments (Student)"
How can class Student
be not applicable, when we declared List, paramethrized by <? extends Person>
, and Student
exactly extends class Person
?
Nevertheless, the following code:
List<? super Person> list = new ArrayList<>();
list.add(clarissa);
compiles and works well (list.get(0)
, passed to println method, shows me the correct result of toString
invocation).
As I understand, List<? super Person>
means, that I can pass to this list any type, that is super type for our Person
class (in our case it is Object
class only). But we see, that, contrary to logic, we can easy add subclass Student to our List<? super Person>
!
OK, put aside our emotions, and let's see, what can happen with Clarissa Starling in our collection. Let's take our class Student
, and add a couple of methods to it:
class Student extends Person {
private int grant;
public Student(String name) {
super(name);
}
public void setGrant(int grant) {
this.grant = grant;
}
public int getGrant() {
return this.grant;
}
}
Then we pass an object, instantiated from this renewed class (our object "clarissa", for example), to List<? extends Person>
. Doing this, we mean, that we can store subclass in the collection of its superclasses. Maybe, I don't understand some fundamenthal ideas, but at this stage I don't see any difference between adding subclass to the collection of its superclasses and the assigning of the reference to object "clarissa" to variable, typed Person. We have the same reducing of invokable methods, when we want to treat one of them, using our superclass variable. So, why List<? extends SomeClass>
does not work the same way, wherein List<? super SomeClass>
works conversely?
- I don't understand the fundamenthal difference between
<T>
(or<E>
, or any other letter from appropriate part of JLS) and<?>
. Both<T>
and<?>
are typeholders, so why we have two "keywords" (this symbols are NOT keywords, I just used this word for emphasizing the heavy meaning of both symbols in Java language) for the same purpose?