0

I have a user-defined class that is supposed to be generic to accept Integers, Floats, Doubles, etc. but also needs to be able to be compared. It looks like:

public class MyClass<T extends Comparable<T>> implements Comparable<MyClass<T>>{
private T myClassObject;
...

And the compareTo method looks like

@Override
public int compareTo(MyClass<T> o){
    return this.myClassObject.compareTo((T) o));
}

Now in a later class that is supposed to be creating an ArrayList of MyClass objects and comparing them, I get:

sort(java.util.List<T>)' in 'java.util.Collections' cannot be applied to '(java.util.ArrayList<MyClass<?>>)

The ArrayList that holds these MyClass objects looks like:

ArrayList<MyClass<?>> temp = new ArrayList<MyClass<?>>();

Is it failing because of the wildcard generic use? Do I need to specify that ? extends Number or something else?

ckrug
  • 17
  • 4
  • 1
    Just wondering: In your class definition you have `T myClassObj` in your compareTo method, you have `this.myClassObject` is this a typo or what is going on here? – ControlAltDel Nov 11 '20 at 00:50
  • It looks like the `compareTo` implementation should be `this.myClassObject.compareTo(o.myClassObject)`. – Louis Wasserman Nov 11 '20 at 00:56
  • @ControlAltDel That was a typo, I'm sorry – ckrug Nov 11 '20 at 01:13
  • @LouisWasserman That seems to be working syntax-wise, but do you know why I would not be able to use `Collections.sort` on an `ArrayList>`? This is where I am having trouble the most. – ckrug Nov 11 '20 at 01:26

1 Answers1

3

The T in the List<T> parameter in the generic Collections.sort method, enforces that you pass in a list with elements that can be compared with each other.

A List<MyClass<?>> can have elements that are not comparable with each other.

With a List<MyClass<?>>, you can potentially put a MyClass<String> and a MyClass<Integer> into the same list!

ArrayList<MyClass<?>> temp = new ArrayList<MyClass<?>>();
temp.add(new MyClass<>(1));
temp.add(new MyClass<>("String"));

To sort this list, Collections.sort would have to know how to compare a MyClass<Integer> with a MyClass<String>! And that's nonsense. More importantly, Comparable<T> doesn't support this operation.

List.sort - a non-generic method - on the other hand, doesn't have this "equality constraint", and does a bunch of unsafe casts, and will throw an exception at runtime if you try to sort a list with different kinds of MyClass.


Though unrelated to the error, note that you implemented Comparable wrongly. It should be:

return myClassObject.compareTo(o.myClassObject);
Sweeper
  • 213,210
  • 22
  • 193
  • 313