Reputation: 850
I have a generic java class that stores comparables:
public class MyGenericStorage<T extends Comparable<T>> {
private T value;
public MyGenericStorage(T value) {
this.value = value;
}
//... methods that use T.compareTo()
}
I also have an abstract class called Person:
public abstract class Person implements Comparable<Person>
and two concrete subclasses, Professor and Student:
public class Professor extends Person
public class Student extends Person
now when I want to create a MyGenericStorage like so, I get an error:
//error: type argument Student is not within bounds of type-variable T
MyGenericStorage<Student> studStore = new MyGenericStorage<Student>(new Student());
//this works:
MyGenericStorage<Person> persStore = new MyGenericStorage<Person>(new Student());
I think this is because I have a fundamental problem with understanding generics. Can someone explain this to me, and also, how to fix it?
EDIT:
I have changed MyGenericStorage to the following:
public class MyGenericStorage<T extends Comparable<? super T>>
and now it seems to work. Can someone explain why?
Upvotes: 5
Views: 503
Reputation: 269657
You can fix this with the following declaration for MyGenericStorage:
class MyGenericStorage<T extends Comparable<? super T>> { …
This means that T
must have a Comparable
implementation that accepts some supertype of T
. In the case of Student
and Professor
, the supertype represented by the bound (?
) is Person
.
Update: "now it seems to work. Can someone explain why?"
Well, I tried in my original answer, but let me give it another shot.
? super T
means "some supertype of T". Suppose T
in this case is Student. So, Student must implement Comparable "for some supertype of Student"
Student
extends Person
, which implements Comparable<Person>
. So, Student does indeed implement Comparable "for some supertype of Student".
If you have questions about Java Generics, the best place to start is Angelika Langer's FAQ. In this case, the entry about bounded wild-cards may be helpful.
Upvotes: 6
Reputation: 10057
public class MyGenericStorage<T extends Comparable<T>>
The above requires you to have the type given to the generic class to extend a class which is omparable with itself. In short, you're saying that Person
must implement Comparable<Student>
and Comparable<Professor>
. That's why it can't be used.
Upvotes: 1
Reputation: 62439
Your problem is that Person
extends Comparable<Person>
, so it's ok, but Student
extends Person and thus it extends Comparable<Person>
not Comparable<Student>
.
In your constraint you are saying <T extends Comparable<T>>
, thus they must be the exact same type. Derived types are not acceptable.
Upvotes: 5