Consider the following simple code
import java.util.*;
public class MainTest<T extends Object1<?,?>> {
List<T> list;
public MainTest(List<T> l) {
this.list=l;
}
public int testCompare() {
// fails to compile here
return list.get(0).compareTo(list.get(1));
}
public static void main(String[]args) {
List<Object1Impl> list = new ArrayList<Object1Impl>();
list.add(new Object1Impl());
list.add(new Object1Impl());
MainTest<Object1Impl> test = new MainTest<Object1Impl>(list);
System.out.println(test.testCompare());
}
}
interface Object1<E, V> extends Comparable<Object1<E,V>> { }
class Object1Impl implements Object1<Integer, Integer>{
public int compareTo(Object1<Integer, Integer> o) { return 0; }
}
I am aware that in this case the program will not compile (fails at testCompare() because T is extending unbounded Object1<?,?>). Is there any alternative to fix this besides making MainTest<T extends Object1<E,V>,E,V>?
EDIT: the error message is
The method compareTo(Object1<capture#1-of ?,capture#2-of ?>) in the type Comparable<Object1<capture#1-of ?,capture#2-of ?>> is not applicable for the arguments (T)
I have read Effective Java book but still can’t really think of a solution..
Also, why is it that if I change interface Object1 into an abstract class the program will compile without any problem? This really puzzles me…
EDIT: when I mean changing into abstract class is as follows
abstract class Object1<E, V> implements Comparable<Object1<E,V>>{
public int compareTo(Object1<E,V> o) { return 0; }
}
class Object1Impl extends Object1<Integer, Integer>{ }
this will work (only if using Eclipse, compiling it manually using javac does not work) but I have no idea why
This is correct; the compiler has no way to verify that
list.get(0)andlist.get(1)are of the same type; one might beObject1<String, Integer>and the otherObject1<BigDecimal, Double>.To make sure that they are of the same type, you would have to bind those types:
As far as I know, Java doesn’t allow binding parameter types to classes without specifically specifying them.