Could anyone please help me understand how does Java's generics work? I understand the concept of it. But for this specific example of the code I don't clearly understand the compiler's error messages.
Example code: Test class
// Test code
public class A < ListType extends Comparable < ListType >> {
// To make the instance variable y
public int y;
// To make the instance variable s
public String s;
//Constructor Method
public A(int requiredY, String requiredS) {
y = requiredY;
s = requiredS;
}
more code here...
}
Then in a different class I wrote
List <A> a = new ArrayList<A>();
more code here...
Collections.sort(a)
The error message I am getting is
test.java:20: error: no suitable method found for sort(List<A>)
Collections.sort(a);
^
method Collections.<T#1>sort(List<T#1>) is not applicable
(inference variable T#1 has incompatible bounds
equality constraints: A
upper bounds: Comparable<? super T#1>)
method Collections.<T#2>sort(List<T#2>,Comparator<? super T#2>) is not applicable
(cannot infer type-variable(s) T#2
(actual and formal argument lists differ in length))
where T#1,T#2 are type-variables:
T#1 extends Comparable<? super T#1> declared in method <T#1>sort(List<T#1>)
T#2 extends Object declared in method <T#2>sort(List<T#2>,Comparator<? super T#2>)
I don't understand why is the compiler complaining about the type parameter. Shouldn't the collections work? Because the type parameters are both mutually comparable.
Either you're writing your question wrong in order to hide the class names, or you're mistaken in representing the generics.
If what you're trying to do is making a class that could be sorted, you can implement Comparable in the class A as others have suggested.
public class A < ListType extends Comparable < ListType >> {
...
}
The above code would require the class A
to accept a class that extends/implements Comparable
, and use ListType
as its type erasure.
Since you don't show how would you use the ListType
to bound a type, I don't think this is what you want.
Usually generics are used to bound the type of parameter you can use in a class, in order to provide a type-safe operations in compile time.
import java.lang.Override;
public class A <ListType extends Comparable<ListType>>{
ListType lt;
A(ListType b){
this.lt = b;
}
static class B implements Comparable<B>{
B(){};
@Override
public int compareTo(B b){
return 0;
}
}
static class C implements Comparable<B>{
C(){};
@Override
public int compareTo(B c){
return 0;
}
}
public static void main(String[] args){
A<B> a = new A<B>(new B()); //OK
A<C> _a = new A<C>(new C()); //ERROR: is not within bound
System.out.println("");
}
}
Because class C
is not implementing a Comparable
class with itself, you cannot pass a class C
variable to the class A
constructor.
If you want to create a type that will accept any classes that extends Comparable
, you could use a wildcard ?
.
public class A <ListType extends Comparable<?>>
or use a single capital letter as type for better code styling
public class A <T extends Comparable<?>>