Java: I don't understand this generics definition at all - java

I have some sorting methods that in order to work they need to accept an object that has the compareTo defined.
The following as part of the generic definition:
private static <SomeType extends Comparable<? super SomeType>>
void doSomeSort(SomeType[] a, int left, int right){
seems to do the trick.
My problem is that I don't really understand what the
<SomeType extends Comparable<? super SomeType>>
actually defines.
It means that you can substiture a type that is an interface that extends Comparable that is instanciated by itself...
I don't get.
Can you please help on clarifying this definition?

This means:
SomeType is a class that extends Comparable<SomeType> or Comparable<Any type that is a superclass or super interface of SomeType>.
The reason of ? super SomeType is that the sort procedure is able to sort an array of SomeType instances if SomeType is able to compare itself to other SomeType instances. If it happens that SomeType extends SomeSuperType, and that any SomeSuperType instance is able to compare itself to other SomeSuperType instances, the sort will compare them without problems.

Ultimately, all you really need to know is that it means:
SomeType x = ...;
SomeType y = ...;
int comparison = x.compareTo(y);
will compile.
More precisely, it means that SomeType implements Comparable<T> for some type T which is in the inheritance hierarchy of SomeType... without you having to specify what the T is but the upshot is that the code above works :)

It translates to:
the type SomeType must extend or implement the class Comparable
the class Comparable itself, in this case, takes some type as parameter, let's call it T.
type T must be SomeType or a superclass of SomeType.
A classic type that fits this pattern is Integer, since it implements Comparable<Integer>.

<SomeType extends Comparable<? super SomeType>>
Comparable is always of a special template type.
So Comparable<String> is something that can be compared to a String, Comparable<BigInteger> is something that can be compared to a BigInteger, and so on.
What's expected here is a SomeType which derives from Comparable<T>. Meaning that SomeType is comparable to other instances. The most trivial thing would be
<SomeType extends Comparable<SomeType>>
Should be clear till now.
Everything thats now added is a simple super keyword.
This means, SomeType needs to be comparable to everything that is of type SomeType or anything above in the derivation hierarchy.
This basically has one advantage: You can later derive your own/additional types from SomeType and this method will still be downward compatible!
Awesome, eh?
For example:
class SomeTypeSuper { ... }
class SomeType extends SomeTypeSuper { ... }
// Now, in your code both is valid:
// Asuming the method `yourMethod` expects a `<SomeType extends Comparable<? super SomeType>>` as parameter.
yourMethod(new SomeTypeSuper()); // This wouldn't be valid if we had used Comparable<SomeType>
yourMethod(new SomeType());

Float is a subclass of Number. We could declare it like so:
class Float extends Number implements Comparable<Float>
But in fact, our Float class is way broader than that. The float class knows how to compare itself with Integers, Bignums, Doubles, etc etc. In fact, our float class knows how to compare itself to *any( number.
class Float extends Number implements Comparable<Number>
class Integer extends Number implements Comparable<Number>
In fact: any number class needs to do this, so the real declaration sare
class Number implements Comparable<Number>
class Integer extends Number
class Float extends Number
Now, the Comparable interface is cool with this. If it wasn't wildcarded, then Floats and Integers wouldn't be able to be Comparable.
But since it is, you can go:
Comparable<Number> array[] = new Comparable<Number>[10];
array[0] = Float.getValue(10);
array[1] = Integer.getValue(11);
sort(array, 0, 1);
You can't do this without the >? super T>.

Related

Usage of super in method declaration

I would like to understand what this Java declaration is doing:
public static <AnyType extends Comparable<? super AnyType>> int mymethod( AnyType x ) {
/* ... */
}
From my basic knowledage of Java, I think all it's doing is telling you that the param x must be of any type, but that type must extend Comparable?
Your understanding is correct. This method indicates that it takes an argument of a type that extends a Comparable (Note that I would have called the type parameter T instead of AnyType for readability).
Now for the super in Comparable<? super AnyType>>, it means that this comparable implementation can actually be, for example, an implementation of Comparable<Object>, that is a comparable type that can be compared to an object. More generally, the type accepted by the method can be a Comparable which can be compared to some type that is a superclass or superinterface of it, hence the keyword super. In other words, the method can be invoked as follows:
// An object of this type can be compared to an Object
class X implements Comparable<Object> {
#Override
public int compareTo(Object o) {
...
}
}
X x = new X();
mymethod(x);
This is a generic method, i.e. its type parametrization is not related to the class' parametrization if any.
The <AnyType extends Comparable<? super AnyType>> part is the generic parametrization of the method.
The extends keyword should not be confused with the extends keyword when declaring a class: in this case it looks more like "is assignable from", in other words, IS-A.
Comparable<T> is an interface - see docs here.
Your method parametrization will make it so that your method accepts any parameter, as long as its type implements Comparable.
Specifically, it needs to be a Comparable of itself or any super-type (that's what the super part means, as opposed to extends).
For instance, you can pass a String argument because String implements Comparable<String> (amongst others).
Yes, parameter must be a sub-type of Comparable.

What is the use of recursive type bound in this case

I have the following piece of code
public static <T extends Comparable<T>> T max(List<T> list){
Iterator<T> iter = list.iterator();
...
// code for finding the max element in the list
...
}
My question is, what is the need for the recursive type bound in this case? As far as my understanding, T extends Comparable < T > means that, T can be compared only with T itself. This comes from the fact that, Class 'T' implements Comparable<T> and so,
class MyClass implements Comparable<MyClass>{
}
If I am wrong here, feel free to correct me.
So now coming to the actual doubt, why do we need to specify < T extends Comparable < T > > ? Any ways the argument List<T> list is going to contain the elements of same type. i.e., suppose I pass a parameter of type List < MyClass2 > , then all the elements are going to be of same type, i.e. MyClass2..
So what is the implication of recursive type bound?
Thanks in advance.
Why do you need to specify <T extends Comparable<T>>? Because Comparable does not require that an implementing class be comparable with itself. You could in theory write something like
class Circle extends Shape implements Comparable<Integer> {
...
}
Since Comparable itself does not make that restriction, you have to on your end when writing the function. However, the given bound is more restrictive than you need it to be. You could make the call
public static <T extends Comparable<? super T>> T max(List<T> list) {
...
}
That would mean T is comparable to some superclass of itself. The reason you want this is given in the Fruit example of rgettman. T is still always comparable to itself, but the comparable does not have to be defined with respect to T itself.
You may have a class hierarchy that forces subclasses to be Comparable to a supertype. For example, you may have
class Fruit extends Comparable<Fruit>
so every piece of Fruit is comparable to another piece of Fruit. Then you have
class Apple extends Fruit ...
class Banana extends Fruit ...
Each subclass is a Fruit, so they are all Comparable<Fruit>, and not Comparable<Apple> and not Comparable<Banana>.
This allows you to find the maximum Fruit (probably a bad example, what's the maximum Fruit?) in a List<Apple>:
List<Apple> apples = getApples();
Fruit maximum = max(apples);
without it having to be a List<Fruit>.
As has been pointed out in comments, it's better for the max method to be:
public static <T extends Comparable<? super T>> T max(List<T> list){
So that each of the following works:
List<Apple> apples = getApples();
Apple maxAppleOfApples = max(apples);
Fruit maxFruitOfApples = max(apples);
List<Banana> bananas = getBananas();
Banana maxBananaOfBananas = max(bananas);
Fruit maxFruitOfBananas = max(bananas);
List<Fruit> fruits = getFruit();
Fruit maxFruitOfFruit = max(fruits);

What is the practical difference between "ArrayList<A>" and "ArrayList<? extends A>"?

I took a look on questions q1, q2, q3, but they don't cover exactly my question.
Note that ArrayList<A> and ArrayList<? extends A> are to be used for declaring a variable or a parameter (not for creating a new generic class).
Are both expressions equivalent when declaring an object attribute (case 1)?:
class Foo {
private ArrayList<A> aList; // == ArrayList<? extends A> aList;
}
EDIT: Are both expressions equivalent from the point of view of what
kind of objects are allowed to be added to aList?, but different
in the same sense as the following case?
but they are different when used in a parameter declaration (case 2)?:
void methodFoo(ArrayList<A> al) != void methodFoo(ArrayList<? extends A> al)
because the first one only allows to be passed ArrayList objects
while the second would be like "more permissive" allowing to be sent
ArrayList<A1> and ArrayList<A2> (as long as A1 and A2 extends A)?
If this is right, is there any other scenario where the two expressions are
effectively different?
Thanks,
Let's have a look at some practical examples. Say, you have:
List<Number> list;
This means that whatever is assigned to this variable or field takes Number and outputs Number, so you always know what to expect. Integer can be added to this list since Integer extends Number. However, you can't assign, say, ArrayList<Long> to this list.
But consider this case:
List<? extends Number> list;
This one says: hey, that's a list of something that extends Number, but no one knows what exacty. What does this mean? This means that you can assign, for example, ArrayList<Long> to this list, which you couldn't in the first case. You still know that whatever this list outputs will be a Number, but you can't put an Integer in it anymore.
There is also an opposite case:
List<? super Number> list;
By printing that you say: that's a list of Number or its superclasses. This is where everything becomes vice-versa. The list can now refer to ArrayList<Object> and ArrayList<Number>. Now we don't know what this list will output. Will it be a Number? Will it be an Object? But now we know that we could put a Number in this list as well as any subclass of Number like Integer or Long.
There is a rule, by the way, which says producer extends, consumer super (PECS for short). If you need the list to output the values, it is a producer, this is the second case. If you need the list to accept values, it is a consumer, this is the third case. If you need both, don't use wildcards (that's the first case).
I hope this clears up matters.
This will explain the difference:
public class GenericsTest {
private ArrayList<A> la;
private ArrayList<? extends A> lexta;
void doListA(ArrayList<A> la) {}
void doListExtA(ArrayList<? extends A> lexta) {}
void tester() {
la = new ArrayList<SubA>(); // Compiler error: Type mismatch
doListA(new ArrayList<SubA>()); // Compiler error: Type mismatch
lexta = new ArrayList<SubA>();
doListExtA(new ArrayList<SubA>());
}
static class A {}
static class SubA extends A {}
}
As you see, calling a method and assigning a variable/instance field have the same rules. Look at the method call as an assignment of your argument to its declared parameter.
ArrayList<A> means a specific class A, where as ArrayList<? extends A> means class A or any class which extands A (Sub class of A) this make it more generic
Using private ArrayList<A> aList; as a variable declaration is not really equivalent to using the wildcard private ArrayList<? extends A> aList;
The wildcarded version will allow you to assign any ArrayLists of types that extend A and A itself but will refuse to add elements to the list as it cannot decide if it is type safe. With ArrayList<A> on the other hand you can only assign ArrayLists (or extensions of ArrayList) of type A and you can then add A elements and any elements extending A to it.
FYI: you should prefer using a more abstract type for declaring your variables/parameters like List<A> or Collection<A>.
The main difference is that if the generic form is used as an argument or return type in a method in a base class (or interface), it allows a greater range of type signatures to count as overriding instead of overloading.
Function override-overload in Java
For example, the following code is legal (in Java 7):
interface A
{
List<? extends Number> getSomeNumbers();
}
class B implements A
{
#Override
public ArrayList<Integer> getSomeNumbers()
{
return new ArrayList<>();
}
}
Difference between Enumeration<? extends ZipEntry> and Enumeration<ZipEntry>?
All of this means that sometimes you can write come code that requires less casts when someone else is using it. Which should not only reducing the amout of typing they have to do, but also eliminate possible failures.
Of course, the problem with Java generics is that they were introduced in a way that was constrained by backwards compatibility. So not everything works that you might think should, and the details get pretty hairy as to what exactly works and what doesn't.
http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ812
It is hard to grasp at first, but inheritance doesn't apply with generics, ie if B extends A, List<B> is not a "subclass" of (can not be assigned to) List<A>. Further, List<? extends A> is not a "subclass" of (can not be assigned to) List<A>.

Java generic method boundaries

What is the difference in following 2 lines?
public static <T extends Comparable<? super T>> int methodX(List<T> data)
public static <T> int methodX(List<? extends Comparable<? super T>> data)
Your first option is a "stricter" parametrisation. Meaning, you're defining the class T with a bunch of restrictions, and then use it later on with List. In your second method, the parameter class T is generic with no conditions, and the Lists class parameter is defined in terms of the parameter T.
The second way is syntactically different as well, with a ? instead of the first option's T, because in the parameter definition you aren't defining the type parameter T but rather using it, so the second method cannot be as specific.
The practical difference that comes out of this is one of inheritance. Your first method needs to be a type that is comparable to a super class of itself, whereas the second type need only be comparable to an unconditional/unrelated T:
public class Person implements Comparable<Number> {
#Override
public int compareTo(Number o) {
return 0;
}
public static <T extends Comparable<? super T>> int methodX(List<T> data) {
return 0;
}
public static <T> int methodY(List<? extends Comparable<? super T>> data) {
return 0;
}
public static void main(String[] args) {
methodX(new ArrayList<Person>()); // stricter ==> compilation error
methodY<Object>(new ArrayList<Person>());
}
}
If you change the Comparable of Person to be able to compare Object or Person (the inheritance tree of the base class) then methodX will also work.
To the callers, the 2nd version is roughly equivalent to
public static <T, X extends Comparable<? super T>> int methodX(List<X> data)
Suppose a caller calls it with an arg whose concrete type List<Foo>. Type inference will conclude that X=Foo. Then we get a new equation about T from X's bound
=>
Foo <: Comparable<? super T>
( A <: B means A is a subtype of B)
If Foo is Comparable at all, it almost certainly implements Comparable<Foo> [2]
=>
Comparable<Foo> <: Comparable<? super T>
=>
T <: Foo
Without further information, inference chooses T=Foo.
Therefore from caller's POV, the two versions are not really different.
Inside method body, the 2nd version does not have access to type parameter X, which is a synthetic one introduced in compilation phase. This means you can only read from data. Things like
X x = data.get(0);
data.set(1, x);
are impossible in version#2; No such problem in version #1 with T.
However we can forward #2 to #1
<T1> method1(List<T1> data){ data.set(...); }
<T2> method2(List<?...> data)
{
method1(data);
}
(they must have difference method names; overloading not allowed since java7)
This is because for the compiler, type of data is really List<X> (it knows the secrete X), so there is no problem calling method1(data) after inferring that T1=X
[1] JLS3, 5.1.10 Capture Conversion
[2] According to the javadoc of Comparable, This interface imposes a total ordering on the objects of each class that implements it. That means if Foo implements Comparable<W>, W must be Foo or a super type of Foo. It is quite improbably for a subclass implementation to define a total order among objects of a super class. So W most definitely should be Foo. Otherwise funny things would happen. The notorious example is 'Timestamp', its javadoc (now) explains why it can't be compared with its supertype Date
The first method expects a list of elements which can be compared against their own class or a supertype of it. Say, real numbers can be compared to any kind of numbers:
class Real extends Number implements Comparable<Number> {
public int compareTo(Number o) ...
}
A bit more restrictive, but still acceptable for your first method is the following:
class Real extends Number implements Comparable<Real> {
public int compareTo(Real o) ...
}
But the second method is actually not very different from this version:
public static int methodY(List<? extends Comparable<?>> data) ...
That is to say, you can replace T with an unnamed wildcard ? because it is used only once in the method signature. It does not use concepts like the same class or an object's own class, etc.

Ensure that objects implement Comparable

I have a litte problem and was wondering how to solve it. I have a generic class Tuple<A,B> and now I would like to sort their tuples according to A and B. It should look like this:
Unsorted:
(1,5)
(2,8)
(6,8)
(1,4)
(2,4)
Sorted:
(1,4)
(1,5)
(2,4)
(2,8)
(6,8)
For that reason I thought of implementing a generic compare method (public int compareTo(Tuple<A, B> other)) in the Tuple class. The only problem is that all objects that you could parameterize the class for (e.g. A=Integer, B=String) have to implement the compareTo method too in order for this whole thing to work.
Is there a way to ensure that all objects the Tuple can hold implement the Comparable interface?
Or are there any other suggestions on how to solve this problem?
Thanks
If you declare the class as
public class Tuple<A extends Comparable<? super A>,
B extends Comparable<? super B>> { ...
then that ensures that both A and B are self-comparable. You can then call compareTo() on any object of type A or B that you have in the class.
You could use recursive type bounds (see also Item 27 of Effective Java) to specify that the components of the tuple extend Comparable, like so:
public class Tuple<A extends Comparable<? super A>, B extends Comparable<? super A>> implements Comparable<Tuple<A, B>> {
A valueA;
B valueB;
#Override
public int compareTo(Tuple<A, B> tuple) {
// Implement comparison logic
return 0;
}
}
This allows you to specify different types for the components of the tuple (Tuple<Integer, String>).
This should do the trick. Any class you specify will have to extend Comparable.
public class Tuple<? extends Comparable> {
}

Categories

Resources