In this method
private <T> int comp(Comparable<T> upper, Comparable<T> lower){ return upper.compareTo((T) lower); }
both parameters have the same type parameter.
Meanwhile, this does not apply to another method:
private int compare (Comparable<?> upper, Comparable<?> lower){ return comp(upper, lower); }
Here, the compiler has no evidence that the type parameters for upper and lower same, and why they refuse to give the green light for compilation.
If you want both methods to share the same type parameter, you can make a type parameter with a class . For instance:
public class YourClass<T> { private int comp(Comparable<T> upper, Comparable<T> lower){ return upper.compareTo((T) lower); } private int compare (Comparable<T> upper, Comparable<T> lower){ return comp(upper, lower); } }
Another option (if you don't like the first one) is to enter the same upper bound for the type parameters for comp() and compare() . For instance:
private <T extends SomeSuperClass> int comp(Comparable<T> upper, Comparable<T> lower){ return upper.compareTo((T) lower); } private <T extends SomeSuperClass> int compare (Comparable<T> upper, Comparable<T> lower){ return comp(upper, lower); }
Alternatively, if you want to avoid casting in the comp() method, you can do:
public class YourClass<T extends SomeSuperClass & Comparable<T>> { private int comp(T upper, T lower){ return upper.compareTo(lower); } private int compare (T upper, T lower){ return comp(upper, lower); } }