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");
Related
I have a couple of questions about generic wildcards in Java:
What is the difference between List<? extends T> and List<? super T>?
What is a bounded wildcard and what is an unbounded wildcard?
In your first question, <? extends T> and <? super T> are examples of bounded wildcards. An unbounded wildcard looks like <?>, and basically means <? extends Object>. It loosely means the generic can be any type. A bounded wildcard (<? extends T> or <? super T>) places a restriction on the type by saying that it either has to extend a specific type (<? extends T> is known as an upper bound), or has to be an ancestor of a specific type (<? super T> is known as a lower bound).
The Java Tutorials have some pretty good explanations of generics in the articles Wildcards and More Fun with Wildcards.
If you have a class hierarchy A, B is a subclass of A, and C and D are both subclasses of B like below
class A {}
class B extends A {}
class C extends B {}
class D extends B {}
Then
List<? extends A> la;
la = new ArrayList<B>();
la = new ArrayList<C>();
la = new ArrayList<D>();
List<? super B> lb;
lb = new ArrayList<A>(); //fine
lb = new ArrayList<C>(); //will not compile
public void someMethod(List<? extends B> lb) {
B b = lb.get(0); // is fine
lb.add(new C()); //will not compile as we do not know the type of the list, only that it is bounded above by B
}
public void otherMethod(List<? super B> lb) {
B b = lb.get(0); // will not compile as we do not know whether the list is of type B, it may be a List<A> and only contain instances of A
lb.add(new B()); // is fine, as we know that it will be a super type of A
}
A bounded wildcard is like ? extends B where B is some type. That is, the type is unknown but a "bound" can be placed on it. In this case, it is bounded by some class, which is a subclass of B.
Josh Bloch also has a good explanation of when to use super and extends in this google io video talk where he mentions the Producer extends Consumer super mnemonic.
From the presentation slides:
Suppose you want to add bulk methods to Stack<E>
void pushAll(Collection<? extends E> src);
– src is an E producer
void popAll(Collection<? super E> dst);
– dst is an E consumer
There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.
Collection<? extends MyObject>
means that it can accept all object who have IS- A relationship with MyObject (i.e. any object which is a type of myObject or we can say any object of any subclass of MyObject) or a object of MyObject class.
For example:
class MyObject {}
class YourObject extends MyObject{}
class OurObject extends MyObject{}
Then,
Collection<? extends MyObject> myObject;
will accept only MyObject or children of MyObject(i.e. any object of type OurObject or YourObject or MyObject, but not any object of superclass of MyObject).
In general,
If a structure contains elements with a type of the form ? extends E, we can get elements out of the structure, but we cannot put
elements into the structure
List<Integer> ints = new ArrayList<Integer>();
ints.add(1);
ints.add(2);
List<? extends Number> nums = ints;
nums.add(3.14); // compile-time error
assert ints.toString().equals("[1, 2, 3.14]");
To put elements into the structure we need another kind of wildcard called Wildcards with super,
List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5, 6, four]");
public static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dst.set(i, src.get(i));
}
}
Generic wildcards are created to make methods that operate on Collection more reusable.
For example, if a method has a parameter List<A>, we can only give List<A> to this method. It is a waste for this method's funtion under some circumstances:
If this method only reads objects from List<A>, then we should be allowed to give List<A-sub> to this method. (Because A-sub IS a A)
If this method only inserts objects to List<A>, then we should be allowed to give List<A-super> to this method. (Because A IS a A-super)
learn by example:
consider the sort() method in Collections class which use both extends and super:
public static <T extends Comparable<? super T>> void sort(List<T> list){...}
so
why <T extends Comparable<...>>: becuase we need list items (T) to be a subclass of the Comparable interface.
why Comparable<? super T>: becuase we allow the Comparable type
to be a Comparable of any super type of T.
Consider
interface Comparable<T>{
public int compareTo(T o);
}
public static <T extends Comparable<? super T>> void sort(List<T> list){...}
public static <T extends Comparable<T>> void sort2(List<T> list){...}
class A implements Comparable<A>{
#Override
public int compareTo(A o) {
...
}
}
class B extends A {
}
List<A> listA = new ArrayList<>();
List<B> listB = new ArrayList<>();
sort(listA); //ok
sort(listB); //ok
sort2(listA); //ok
sort2(listB); //Error
I was trying to solve a problem where I am not able to understand part of the answer.
Following is the class BackLister:
public class BackLister {
// INSERT HERE
{
List<T> output = new LinkedList<T>();
for (T t : input)
output.add(0, t);
return output;
}
}
The question asks which can be inserted at // INSERT HERE in the BackLister class to compile and run without error?
Following are the options:
A. public static <T> List<T> backwards(List<T> input)
B. public static <T> List<T> backwards(List<? extends T> input)
C. public static <T> List<T> backwards(List<? super T> input)
D. public static <T> List<? extends T> backwards(List<T> input)
E. public static <T> List<? super T> backwards(List<T> input)
F. public static <? extends T> List<T> backwards(List<T> input)
G. public static <? super T> List<T> backwards(List<T> input)
I understand that that A and B are correct, as for for (T t : input) to work the elements in input should be of type T or subtype of T.
But I am not able to understand why D and E options are correct?
I understand the following:
public static <T> List<? extends T> backwards(List<T> input)
means that the return type should be a List of T or subclass
of T.
public static <T> List<? super T> backwards(List<T> input) means that the return type should be a List of T or
superclass of T.
Could somebody help me understand it?
There is difference between each of them and I'm going to explain most of them. Let's start with our example. I use this class hierarchy:
class Food {}
class Apple extends Food {}
class Orange extends Food {}
class RedApple extends Apple {}
List<Food> listFood = new ArrayList<>();
List<Apple> listApple = new ArrayList<>();
List<Orange> listOrange = new ArrayList<>();
List<RedApple> listRedApple = new ArrayList<>();
ow start with first one:
A. public static <T> List<T> backwards(List<T> input)
This method will only accept List<T> and return List<T> and you can not send listApple and return listRedApple. (however your return list can contain RedApple because it extends Apple but type of list must be List<Apple> and nothing else)
B. public static <T> List<T> backwards(List<? extends T> input)
You can send listRedApple and return listApple but you know that listRedApple is "? extend Apple" so in the method body java recognize T as Apple. Then if you use can add elements in listRedApple which sent as argument, you can add Apple in listRedApple which is not true!!! so compiler avoid it and give compile error. In B you can only read elements (and get it as T) but you can not add anything to it.
C. public static <T> List<T> backwards(List<? super T> input)
You can send listApple and then in method body you can add anything extends Apple because compiler see T as Apple and in a list of anything which is super of T, you can add anything extends Apple.
However this time, you can not read anything because you don't know its type except you get it as Object. (It is a list of "? super T")
As you see here there is difference between ? super and ? extend. one of them give you write access and other give you read access. This is the real use of wildcard.
D. public static <T> List<? extends T> backwards(List<T> input)
E. public static <T> List<? super T> backwards(List<T> input)
If you send listApple then you return List<? extends Apple> but you can's assign it to any of listFood or listApple or listRedApple because List<? extends Apple> maybe contain Apple or RedApple or something else and we can't assign it to any List<T> because then we can add T to that list and maybe T and ? extends T is not same. this is same for both D and E. You can assign it to List<? extends Apple> for 'E and List<? super Apple> for D and send them to a method which need them as parameter.
F. public static <? extends T> List<T> backwards(List<T> input)
G. public static <? super T> List<T> backwards(List<T> input)
Give compile errors because wildcard can not used like this.
I hope this help you.
If something is wrong, any comment is appreciated.
Options D and E are valid because there exist a super-subtype relationships among generic types that allow you to define a larger set of types that the method can accept or return.
Consequently, the following is valid (D):
public static <T> List<? extends T> backwards(List<T> input) {
return List.of();
}
// there exist a super-subtype relationships among List<? extends Number> and List<Long>
List<? extends Number> list = backwards(List.<Long>of(1L, 2L));
because the type Long is a member of the type family that the wildcard ? extends Number denotes (the family of types that are subtypes of Number and the type Number itself).
The next code snippet is also valid (E):
public static <T> List<? super T> backwards(List<T> input) {
return List.of();
}
List<? super Long> ints = backwards(List.<Long>of(1L, 2L));
because the type Long is a member of the type family that the wildcard ? super Long denotes (the family of types that are supertypes of Long and the type Long itself).
So, your understanding is correct.
Further reading.
Below image describes the sub-typing relation in Generics:
List<T> is a subtype of List<? super T>
Also List<T> is a subtype of List<? extends T>
This is why options D and E are correct.
You can refer the page : https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html
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.
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
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>.