I can't see any difference between this default sort method(from java.util.Collections)
public static <T extends Comparable<? super T>> void sort(List<T> list) {
//implementation
}
..and this :
public static <T extends Comparable<T>> void mySort(List<T> list) {
//implementation
}
Although I know about the differences between the 'upper' and 'lower' bounded wildcards,I still don't understand why they use '? super T' instead of simple 'T' in this case.If I use these methods,I get the same result with both of them.Any suggestions?
With your version, the following will not compile:
class Base implements Comparable<Base> { ... }
class Derived extends Base { ... }
List<Derived> list = ...;
mySort(list);
Derived does not extend Comparable<Derived>. However, it does extend Comparable<Base> (and thus, Comparable<? super Derived>).
From what I understood, "<? super T>" is a way to recognize that the CompareTo method is not implemented in T itself, but inherited by a SuperClass.
Related
What should be the generic part of the definition of the Subclass
I have a super class I don't want to modify the generic part in the definition of Sort
public class Sort<T extends Comparable<? super T>> {
public abstract void sort(List<T> thingToSort);
}
I want to write
public void HeapSort"<>" extends Sort"<>" {
}
what should be kept in generic part of definition of HeapSort
and somewhere in main
HeapSort sort = new HeapSort<>(new ArrayList(Arrays.asList(1,2,3,4)));
You just need to propagate T with its bounds to the extending class:
public void HeapSort<T extends Comparable<? super T>> extends Sort<T> { ... }
This effectively defines a type argument T on HeapSort that is used to instantiate the type argument on the superclass Sort.
You can then create a new HeapSort like so:
HeapSort<Integer> sort = new HeapSort<>(Arrays.asList(1,2,3,4));
In this The Grey Blog tutorial about Java Generics, the author tries to show how to write a method head that uses Generics in such a way as to check whether a parent class of the object that method takes as an argument implements a certain interface.
The following classes are involved:
public interface Juicy<T> {
Juice<T> squeeze();
}
class Orange extends Fruit implements Juicy<Orange>;
class RedOrange extends Orange;
Now we want to "squeeze" a List of red oranges using the squeeze method that only the class Orange implements:
<T extends Juicy<? super T>> List<Juice<? super T>> squeezeSuperExtends(List<? extends T> fruits);
At the beginning <T extends Juicy<? super T>> declares that T must either directly implement the interface Juicy or be subclass of a class that implements Juicy (I hope I am right so far?)
But then, when the method declares its argument types (List<? extends T> fruits) it again declares that the List can contain objects ob T or of any of Ts subclasses.
Wouldn't it be enough to write either the first part:
<T extends Juicy<T>> List<Juice<? super T>> squeezeSuperExtends2(List<? extends T> fruits)
or the last part:
<T extends Juicy<? super T>> List<Juice<? super T>> squeezeSuperExtends3(List<T> fruits)
Thank you so much!
When I try to complete a task, there's one case need to be handled: throw exception of generic type of class is not comparable. Refer to the following code for the detail.
public class C <T>
{
public C()
{
// throw exception if T is not comparable
}
}
You can enforce the generic to be a subclass of Comparator like so:
public class C <T extends Comparator> {
public C(){
}
}
As you see in the below code, it would be a good idea to add another generic (here it is K), which you supply to Comparator, since the generic of Comparator will otherwise default to Object.
public class C <K, T extends Comparator<K>> {
public C(){
}
}
You generally use this in the form of T x K, where T is the generic, x is super or extends and K is the class/interface.
Comparator docs
You should make sure that the generic parameter T is a Comparableby writing:
public class C <T extends Comparable>
There are two ways:
1) Make it T extends Comparable, so you know it will always be.
2) In the constructor, pass Class < T > as a parameter, so you'll know at runtime what T is. (because it's erased)
Add a generic constraint, that is would be better since it will be handle it at compile time rather than throw an exception on runtime.
class C <T extends Comparable>
You should verify that your parameter T is Comparable.
public class C <T extends Comparable>
This is the same if you want a generic type implements some interface.
public class C <T implements <interface what you want> >
Or if you want that were a superclass of another one.
public class C <T super <class what you want> >
If you always want the type T to implement Comparable you can enforce this as follows.
public class C<T extends Comparable<? super T>> {
public C() {
}
}
This is better than throwing an exception at runtime. It will not even compile if someone tries to write new C<some non-Comparable type>(). Note that Comparable is a generic type, so it should not be used without type parameters; it should not simply be
public class C<T extends Comparable>
If the type T will not always implement Comparable, but you want a specific constructor that will only work for Comparable types, then the answer is that you can't do this with constructors, but you can do it with a static method.
public class C<T> {
public C() {
// Constructor that works with any T
}
public static <T extends Comparable<? super T>> C<T> getNew() {
C<T> c = new C<>();
// Do stuff that depends on T being Comparable
return c;
}
}
I am trying to implement a generic DDLinkedList of Entries. I have the following classes defined.
class DoublyLinkedList<T extends Comparable<T>>
class DLLNode<T extends Comparable<T>>
Entry<K extends Comparable<K>, V> implements Comparable<Entry<K, V>>
Once I try to create an array of DoublyLinkedlist of type Entry as below:
DoublyLinkedList<DLLNode<Entry<K, V>>> array[] = (DoublyLinkedList<DLLNode<Entry<K, V>>>[]) new DoublyLinkedList[TABLE_SIZE];
I get an error message:
"The type DLLNode<Entry<K,V>> is not a valid substitute for the bounded
parameter <T extends Comparable<T>> of the type DoublyLinkedList<T>"
From my other standing I thought I could make a Generic Type T of Entry.
My question:
Am I going about the wrong way of doing this or am I implementing it wrong?
Your definition for DoublyLinkedList says that it must take a type which is comparable with itself. But your definition for DLLNode does not implement Comparable<DLLNode<T>> which means that DLLNode is not comparable with its own type. So you can't use DLLNode as a parameter type in DoublyLinkedList.
DLLNode needs to actually implement Comparable and not use it as its generic type.
Also your syntax is way off. Arrays cannot use generics. The best you can do is this:
DoublyLinkedList<?> array[] = new DoublyLinkedList[TABLE_SIZE];
You need to do:
class DoublyLinkedList<T extends Comparable<? super T>> {}
class DLLNode<T extends Comparable<? super T>> implements Comparable<DLLNode<T>> {
public int compareTo(DLLNode<T> other) {
return 0;
}
}
abstract class Entry<K extends Comparable<? super K>, V> implements Comparable<Entry<K, V>> {}
class HashEntry<K extends Comparable<? super K>, V> extends Entry<K, V> {
public int compareTo(Entry<K, V> other) {
return 0;
}
}
Then wherever you decide to use this:
DoublyLinkedList<DLLNode<HashEntry<K, V>>> array[] = new DoublyLinkedList[TABLE_SIZE];
The reason why this works is because of that <? super T> declared for the DLLNode class. If you just have <T>, this will not work because HashEntry will not be comparable. Generics in Java is a bit of a pain to get right.
I am trying to implement generics in Java using Comparable<T> interface.
public static <T> T[] sort(T[] a) {
//need to compare 2 elements of a
}
Let's say, I want to override the compareTo method for the above type T in the Comparable interface. I.e. I need to compare two elements of my type T, how will I do it? I don't know what my T type will be.
You need to set a type constraint on your method.
public static <T extends Comparable<? super T>> T[] sort (T[] a)
{
//need to compare 2 elements of a
}
This forces the type T to have the compareTo(T other) method. This means you can do the following in your method:
if (a[i].compareTo(a[j]) > 0) }
}
Try using <T extends Comparable<T>> and then compareTo
Old question but...
As jjnguy responded, you need to use:
public static <T extends Comparable<? super T>> T[] sort(T[] a) {
...
}
Consider the following:
public class A implements Comparable<A> {}
public class B extends A {}
The class B implicitly implements Comparable<A>, not Comparable<B>, hence your sort method could not be used on an array of B's if used Comparable<T> instead of Comparable<? super T>. To be more explicit:
public static <T extends Comparable<T>> T[] brokenSort(T[] a) {
...
}
would work just fine in the following case:
A[] data = new A[3];
...
data = brokenSort(A);
because in this case the type parameter T would be bound to A. The following would produce a compiler error:
B[] data = new B[3];
...
data = brokenSort(B);
because T cannot be bound to B since B does not implement Comparable<B>.