Nested compare() call - possible to change generics information? - java

private interface Internal {
<T extends Comparable<? super T>> void compare(final T left, T right);
}
private final Internal internal = ...;
public <T> void compare(final Comparable<T> left, final Comparable<T> right) {
this.internal.compare(left, right);
}
I'm seeing a compiler error on .compare(left, right):
Bound mismatch: The generic method compare(T, T) of type
MyClass.Internal is not applicable for the arguments
(Comparable<T>, Comparable<T>). The inferred type Comparable<T> is not a valid
substitute for the bounded parameter <T extends Comparable<? super T>>
Is there any reasonable way to accomplish the transition I'm trying to make - taking in Comparable from the public-facing method and using it in a type-safe manner in the internal implementation? Or do I need the same type information for my outer method as I have for the inner one?

Comparable is just defined as:
public interface Comparable<T>
It means that implementing classes can compareTo anything they want. So for example I can do this:
class Vague
implements Comparable<String> {
#Override
public int compareTo(String str) {
return 0;
}
}
When you have a type as:
<T extends Comparable<? super T>>
It means that T must be a Comparable that also compares to a T or superclass of T.
On the other hand, when you just have <T> and then Comparable<T> it can be a Comparable that compares to anything.
The class Vague is a Comparable<T> but not a T extends Comparable<? super T>. Obviously Vague is not a good Comparable.
So yes, these are inconvertible types and the method signatures will have to be made to match. <T extends Comparable<? super T>> is the type safe way to declare a Comparable parameter generically. It means two instances of T can be compared to each other.

Related

Java Generic Types and Entry

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.

How to understand the Java doc syntax

For example, I see
static <T extends Comparable<? super T>> void parallelSort(T[] a)
Sorts the specified array of objects into
ascending order, according to the natural ordering of its elements.
So I get this is a static method and what it does, but what does <T extends Comparable<? super T>> mean (return type, but what is it, is it the same way I would write in the code, or a syntax used in the documentation to show several possible values)
<T extends Comparable<? super T>> is not the return type. void is the return type. A generic specification before the return type is for type inference.
The argument (T[]) type is inferred from the call, and must be something that extends Comparable<? super T>
Suppose you have a class defined:
class Foo extends Comparable<Foo> { ... }
That means:
Foo[] fooArray = ...
parallelSort(fooArray);
is legal, and inside the parallelSort() method, T will be of type Foo (which implements the Comparable interface)
Here's a simple, less complicated example without the recursive type. In this case, it says it returns a list of the inferred type:
public static <T> <List<T>> myMethod(T arg) {
List<T> list = new ArrayList<T>();
list.add(arg);
return list;
}
The type is inferred from the argument:
List<String> list = myMethod("hi");

What does self comparable interface do in Collections Class?

While practicing Reflection I came to know about SelfComparable Interface in Collections class
interface java.util.Collections$SelfComparable
What does this interface use for ?
It doesn't do anything. It is private so you can't import it.
It is really a comment that the type is "SelfComparable" and is not actually used.
Nothing implement this interface. The code which uses it relies on the fact it will be discarded at runtime.
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {
if (comp==null)
return (T)max((Collection<SelfComparable>) (Collection) coll);
could have been
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp) {
if (comp==null)
return (T)max(/*SelfComparable*/ (Collection) coll);
as it will be ignored at runtime.
From source:
private interface SelfComparable extends Comparable<SelfComparable> {}
This is nothing more than a marker over Comparable<SelfComparable>, which basically means that it is a marker for comparables that compare to self. Its use is somewhat superfluous.
It's used as:
return (T)min((Collection<SelfComparable>) (Collection) coll);
on line 662 where it basically casts a collection to Collection, and then performs a cast for the generic parameter to be a SelfComparable which just extends Comparable.

In the following example, is "List<? extends T>" necessary, or will "List<T>" do the same thing?

I understand that
List<? extends T>
allows for the list to be any sub-type of T (or T itself), and that
List<T>
only allows for lists of the type T. However, take a look at the following method signature:
public static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end){
And the following classes:
public class ClassA{
}
public class ClassB extends ClassA implements Comparable<ClassA>{
public int compareTo(ClassA s){
//do comparison
}
}
public class ClassC extends ClassB{
}
Let's assume T is ClassB, and I want to pass a sub-type of T (ClassC) for my list:
public static void main(String[] args){
List<ClassC> myC = new ArrayList<ClassC>();
ClassC a = findMax(myC, 2, 3);
}
In this case, how does java infer that T is ClassB, and not ClassC? And if it isn't able to infer ClassB (and actually infers ClassC instead) then wouldn't the following method signature (without the "List") be equivalent?
public static <T extends Object & Comparable<? super T>> T findMax(List<T> myList, int begin, int end){
Thanks,
Jack
Firstly, ? extends Object adds no value, because everything extends Object, so these two methods are equivalent:
public static <T extends Object & Comparable<? super T>> T findMax(List<T> myList, int begin, int end)
public static <T extends Comparable<? super T>> T findMax(List<T> myList, int begin, int end)
Having made that simplification, your question is basically are these equivalent:
public static <T extends Comparable<? super T>> T findMax(List<T> myList, int begin, int end)
public static <T extends Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end)
They are (not* the same.
The reason is, with the second method, you can pass in a List with a type that's a subclass of the returned type, whereas in the first method the List's type must be the same type as the returned type.
The way type inference works, T is always going to be inferred to the type param of the list you call the function with, so the additional liberty given by <? extends T> will never be used. You can write List<T> with the same result.
Answering to the subtler point raised by bohemian, the inferred type will be assignable to any supertype as well, so once again no flexibility is added by the longer signature.
how does java infer that T is ClassB, and not ClassC?
I don't follow you here. Generics is a compile type technique.
The erasure of public static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end) is to Object i.e.
this compiles to public static Object findMax(List myList, int begin, int end)
When you instantiate the list List<ClassC> myC = new ArrayList<ClassC>(); and pass it to the method, the compiler ensures type safety, essentially that the pass list complies with the declaration. In this case Class C implements a Comparable and you could return back Class B since the compiler would accept it.
Generics do not exist at runtime.
Update after comment:
This public static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end)
is not the same as:
public static <T extends Object & Comparable<? super T>> T findMax(List<T> myList, int begin, int end)
This is not about type inference. The compiler would make the same type inference here either it was T or ? extends T in this specific case.
The difference lies in the contract. The public static <T extends Object & Comparable<? super T>> T findMax(List<? extends T> myList, int begin, int end) declares a method that guarantees not to modify your collection (at least not a way that would corrupt it).
The List<? extends T> myList essentially makes list a read-only list inside the body of findMax which can not add any instance in the list (either T or subtype of T) except null.
If you declared List<T> myList then it is not a read-only list and one could add elements in your list e.g. inside findMax you could do: myList.add(myList.get(0)); This is not possible with the declaration of findMax as List<? extends T> myList

Using generics in Comparable

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>.

Categories

Resources