T extends Comparable <T>
I have the following class.
class MyClass<T> It uses the following constructor.
MyClass(Comparator<T> comparator, Collection<? extends T> data) And he has a field that is set in the constructor as follows:
this.data = Collections.unmodifiableCollection(data); In the special case, when T implements Comparable, I do not want to require the transfer of a comparator, since I can just use the natural order. So I thought I should use this constructor:
public <T extends Comparable<T>> MyClass(Collection<T> data) But there seems to be a type mismatch: cannot convert from Collection<T> to Collection<? extends T> Collection<T> to Collection<? extends T> to the above assignment operator. I tried all kinds of things: adding more general options, etc., but no one works. I can't seem to specify a binding that states: if you have a type T that implements Comparable, do the direct thing.
Any ideas?
Thanks.
Unfortunately, I do not think that such a system "if Comparable do this else do that" is possible with a system such as Java.
You can separate Comparable and non-Comparable cases into separate classes and hide them behind the interface, something like this:
interface Interface<T> { public void processData(); } class MyClass<T> implements Interface<T> { private final Collection<? extends T> data; MyClass(Comparator<T> comparator, Collection<? extends T> data) { this.data = data; } public void processData() { // ... } } class MyCompClass<T extends Comparable<T>> implements Interface<T> { private final Collection<? extends T> data; MyCompClass(Collection<? extends T> data) { this.data = data; } public void processData() { // ... } } class Factory { static <T extends Comparable<T>> Interface<T> create(Collection<? extends T> data) { return new MyCompClass<T>(data); } static <T> Interface<T> create(Comparator<T> comparator, Collection<? extends T> data) { return new MyClass<T>(comparator, data); } } But this can lead to a lot of duplicate code. Another option is to leave MyClass, which requires a comparator in its constructor, and build this comparator in the factory:
class MyClass<T> { private final Collection<? extends T> data; MyClass(Comparator<T> comparator, Collection<? extends T> data) { this.data = data; } public void processData() { // ... } } class Factory { static <T extends Comparable<T>> MyClass<T> create(Collection<? extends T> data) { return new MyClass<T>(new Comparator<T>() { public int compare(T o1, T o2) { return o1.compareTo(o2); } }, data); } static <T> MyClass<T> create(Comparator<T> comparator, Collection<? extends T> data) { return new MyClass<T>(comparator, data); } } I agree that this seems impossible as a direct solution
class MyClass<T> { Collection<? extends T> data; public MyClass(Comparator<T> comparator, Collection<? extends T> data) { this.data = data; } public <E extends T & Comparable<T>> MyClass(Collection<E> data) { this.data = data; } } rejected by the compiler with
You cannot specify an optional
Comparable<T>binding when the first binding is a type parameter
See also Why can't I use a type argument in a type parameter with a few constraints? (in particular, Chris Povirkaโs answer).
As for the decisions, I agree with Chris B.
You can use the usual constructor for the first case and the factory method for the second:
class MyClass<T> { Collection<? extends T> data; Comparator<? super T> comparator; public MyClass(Comparator<? super T> comparator, Collection<? extends T> data) { this.data = data; this.comparator = comparator; } public static <T extends Comparable<? super T>> MyClass<T> fromComparable(Collection<T> data) { return new MyClass<T>(Collections.reverseOrder(Collections.reverseOrder()), data); } }