Explanation of the Collections.max signature - java

I was reading an article on Java Generics when I stumbled on this method signature:
static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll);
The part that I don't get is why we need to have
Collection<? extends T> coll
wouldn't
Collection<T> coll
do as well?
Could someone please explain why the following signature is not adequate?
static <T extends Object & Comparable<? super T>> T max(Collection<T> coll);
Thanks in advance for your replies. This keeps puzzling me for quite some time now..

Gábor is correct. The wildcard allows the static type of the returned object to differ from the declared parameter type of the collection you input. For example, given these classes:
interface S extends Comparable<S> {}
class A implements S {
#Override
public int compareTo(final #NotNull S o) {
return 0;
}
}
class B implements S {
#Override
public int compareTo(final #NotNull S o) {
return 0;
}
}
And this class:
class Test {
#Nullable
static <T extends Comparable<? super T>> T extendsMax(
Collection<? extends T> coll) {
return null;
}
#Nullable
static <T extends Comparable<? super T>> T max(Collection<T> coll) {
return null;
}
}
Observe what calls compile and what calls do not:
public static void main(String[] args) {
final Collection<S> sColl = new ArrayList<>();
final Collection<A> aColl = new ArrayList<>();
final Collection<B> bColl = new ArrayList<>();
final S s1 = Test.<S> extendsMax(sColl); // compiles, T = S, <? extends T> = S
final S s2 = Test.<S> extendsMax(aColl); // compiles, T = S, <? extends T> = A
final S s3 = Test.<S> extendsMax(bColl); // compiles, T = S, <? extends T> = B
final A a1 = Test.<A> extendsMax(aColl); // compiles, T = A
final B b1 = Test.<B> extendsMax(bColl); // compiles, T = B
final S s4 = Test.<S> max(sColl); // compiles, T = S
final S s5 = Test.<S> max(aColl); // does not compile, T = S, T != A
final S s6 = Test.<S> max(bColl); // does not compile, T = S, T != B
final S s7 = Test.max(aColl); // compiles, but because T = A, and A
// can be assigned to S
}
So the wildcard allows for some flexibility. While you can omit the wildcard (and to be honest, I can't think of a place off the top of my head where the wildcard is required), there is a reason it is there.
Tom is also incorrect. You can add null to collections with a wildcard (if the collection supports add() in the first place):
List<? extends Number> list = new ArrayList<>();
list.add(null); // compiles, and should execute just fine
And because add(), remove(), and most other mutators in the Collection interface are optional operations, it wouldn't be safe to mutate the collection anyways through those methods if the parameter is just declared as a Collection. In addition, it's generally possible to use iterator().remove() or something of the sort to remove elements from collections regardless of whether they were declared with a wildcard, especially for the ones already included in the Java Collections Framework.
So while a wildcard does limit what you can do with a collection, it should not be used as a way to prevent changes to a collection.

Related

java PECS List<? super T> dest and List<T> dest difference?

public static <T> void copy1(List<? extends T> src, List<? super T> dest) {
for (int i = 0; i < src.size(); i++) {
dest.add(src.get(i));
}
}
public static <T> void copy2(List<? extends T> src, List<T> dest) {
for (int i = 0; i < src.size(); i++) {
dest.add(src.get(i));
}
}
top 2 method both can implements PECS Effect,but what difference ??
thank you !!
PECS -> Producer Extends Consumer Super
? extends T -> from the list perspective, it acts as a producer to others. You can get items from it (list produces), but you can’t insert into it. In Java world, it is called covariance.
? super T-->This is called consumer behavior, because, from the list perspective, it allows to add items to it (list consumes), but not useful in type-safety reading (producing). It's contravariance.
T -->In here, we can insert any subtypes of T class into the list. And when we reading, it will return a type of T instance. This is called Invariance.
class A{
public int a;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
}
class B extends A
{
public int b;
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
}
public class GenericsDemo {
public static void main(String[] args) {
List<A> invariant = new ArrayList<>();
List<? extends A> covariant = new ArrayList<>();
List<? super A> contravariant = new ArrayList<>();
invariant.add(new B());
invariant.get(0).getA();
//Error as it expect the instance of A while reading
// invariant.get(0).getB();
//Error it will be used to read the values, we can't insert any values in it.
// We will use this construct places like defining params to a function
//covariant.add(new B());
//covariant.add(new A());
contravariant.add(new A());
contravariant.add(new B());
//Error, it will be used to write only
//While reading, it will give you object type
//contravariant.get(0).getA();
//We can type-cast while reading
A a = (A) contravariant.get(0);
a.getA();
copy1(invariant,invariant);
copy2(invariant,invariant);
//Error due to the dest param requires super of T
// copy1(covariant,covariant);
//Error due to the dest param requires of T
//copy2(covariant,covariant);
copy1(covariant,contravariant);
copy2(covariant,contravariant);
}
public static <T> void copy1(List<? extends T> src, List<? super T> dest) {
for (int i = 0; i < src.size(); i++) {
dest.add(src.get(i));
}
}
public static <T> void copy2(List<? extends T> src, List<T> dest) {
for (int i = 0; i < src.size(); i++) {
dest.add(src.get(i));
}
}
}
Method 1 -- > public static void copy1(List src, List dest)
dest list will consume anything with type T and it's sub class. But, when we read it, it will return an instance with Object type which we need to be type caste.
Methpd 2---> public static void copy2(List src, List dest)
dest list will consume anything with type T and it's sub class. But, when we read it, it will return the instance of T
Reference --> https://medium.com/#isuru89/java-producer-extends-consumer-super-9fbb0e7dd268
PS:- Sorry for long answer.
In this specific example both methods are the same, because the type T is unbounded itself. Thus, both declarations just say that the dst parameter lists elements must be a superclass of src parameter lists elements, using ? super T in copy1() does not add something new here.
PECS rule does not mean you must always put extends or super everywhere. Here is the complete example of PECS-compatible declaration from Item 32 of J. Bloch "Effective Java":
public static <E> Set<E> union(Set<? extends E> s1, Set<? extends E> s2);
No need to use a return type as Set<? super E> here.

Java Generics bounded wild card usages before the return type of a method

In the class below, in method m1, is there really any use of mentioning K extends Runnablebefore the method return type? I cannot return anything other than Collection<K> anyways. And if I want to return any subclass of Runnable I would have specified the method like,
static <T> Collection<? extends Runnable> m1(ArrayList<T> l)
Does the K extends Runnable before the method return type have any significance at all? I get no compilation error for this code either
public class MainClass {
public static void main(String[] args) {
ArrayList<Thread> l = new ArrayList<>();
l.add(new Thread());
l.add(new Thread());
m1(l);
}
static <T, K extends Runnable> Collection<K> m1(ArrayList<T> l) {
ArrayList<K> r = new ArrayList<>();
return r;
}
}
By having the parameter K, you can let the caller decide what kind of collection it wants back:
public class Test {
static <T, K extends Runnable> Collection<K> m1(ArrayList<T> l) {
ArrayList<K> r = new ArrayList<>();
return r;
}
static void callingIt(){
ArrayList<?> list = new ArrayList<>();
Collection<Thread> threads = m1(list);
Collection<Runnable> runnables = m1(list);
Collection<MyTask> special = m1(list);
}
class MyTask extends Thread{}
}
If you only had Collection<? extends Runnable> then the caller cannot get back a Collection<Thread>.
But unless the K is connected to something else, I cannot see how this would work except for empty result lists (because as soon as you want to add something to r, you will have to make sure it is an instance of K).
You can see this pattern being used in Collections.emptyList:
public static final List EMPTY_LIST = new EmptyList<>();
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
The method returns the same thing as the field, but because it is a method, the caller can use it to produce generically typed lists of any type (whereas the field cannot be flexible like this).
There is an unchecked cast in there (with a warning), but since the list is empty, we (unlike the compiler) know it is safe.

In (ListChangeListener.Change<? extends Classname> change) what is the use of "?" in it? [duplicate]

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

Why producer in Collections.max() is a bounded wildcard? [duplicate]

In Java, the Collections class contains the following method:
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c)
Its signature is well-known for its advanced use of generics,
so much that it is mentioned in the Java in a Nutshell book
and in the official Sun Generics Tutorial.
However, I could not find a convincing answer to the following question:
Why is the formal parameter of type Collection<? extends T>, rather
than Collection<T>? What's the added benefit?
Type inference is a tricky topic that I'll admit that I don't know that much about. However, examine this example:
public class ScratchPad {
private static class A implements Comparable<A> {
public int compareTo(A o) { return 0; }
}
private static class B extends A {}
private static class C extends B {}
public static void main(String[] args)
{
Collection<C> coll = null;
B b = Scratchpad.<B>min(coll);
}
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> c) {
return null;
}
//public static <T extends Object & Comparable<? super T>> T min(Collection<T> c) {
// return null;
//}
}
Consider that the first signature of min() allows the call to compile whereas the second does not. This isn't a very practical example, since one must ask why I would be explicitly typing the method to <B>, but perhaps there is an implicit inference where B would be the inferred type.
One benefit of the ? is that it prohibits additions of items to the Collection
I think it actually doesn't give you anything more for this method, however its a good habit to get into when T is part of the class and not just a static method.
They are including it here so it can become the new convention where every generic should be extended by ?
A class of T should follow PECS: What is PECS (Producer Extends Consumer Super)?
But a static method doesn't need to (at least the parameters, the return value should always)
This is to support a legacy signature of the method in Java 1.4 ( and before ).
Prior to Java 5 the signature for these methods was
public static Object min ( Collection c );
With multiple bounds the erasure rules make the first bound the raw type of the method, so without Object & the signature would be
public static Comparable min ( Collection c );
and legacy code would break.
This is taken from O'Reilly's Java Generics and Collections book, chapter 3.6
Building on the comments I put on Mark's answer, if you have something like
class Play {
class A implements Comparable<A> {
#Override
public int compareTo(A o) {
return 0;
}
}
class B extends A {
}
class C extends A {
}
public static <T extends Object & Comparable<? super T>> T min(
Collection<? extends T> c) {
Iterator<? extends T> i = c.iterator();
T candidate = i.next();
while (i.hasNext()) {
T next = i.next();
if (next.compareTo(candidate) < 0)
candidate = next;
}
return candidate;
}
public static List<? extends A> getMixedList() {
Play p = new Play();
ArrayList<A> c = new ArrayList<A>();
c.add(p.new C());
c.add(p.new B());
return c;
}
public static void main(String[] args) {
ArrayList<A> c = new ArrayList<A>();
Collection<? extends A> coll = getMixedList();
A a = Play.min(coll);
}
}
It's clearer that min returns an object of type A (the actual signature is <A> A Play.min(Collection<? extends A> c) ). If you leave min(Collection<T>) without the extends part then Play.min(coll) will have the following signature <? extends A> ? extends A Play.min(Collection<? extends A> c) which isn't as clear.

Java generics - special case of extended and super usage

Is there any conceptual difference between these two methods?
public static <T> void add1(final Collection<T> drivers, final Collection<? super T> persons) {
persons.addAll(drivers);
}
and
public static <T> void add2(final Collection<? extends T> drivers, final Collection<T> persons) {
persons.addAll(drivers);
}
The following main method compiles without any warnings and executes without any runtime-exceptions. And the result is the expected one - 4.
public static void main(String[] args) {
final Person person1 = new Person();
final Person person2 = new Person();
final Collection<Person> persons = new ArrayList<>();
persons.add(person1);
persons.add(person2);
final Driver driver1 = new Driver();
final Collection<Driver> drivers = new ArrayList<>();
drivers.add(driver1);
add1(drivers, persons);
add2(drivers, persons);
System.out.println(persons.size());
}
I am aware of PECS principle, and since persons in the first method is a consumer, super should be use, respectively - extends should be used for drivers in the second method. But is there any gotchas? Any difference that I may miss? If not, which one of the versions is preferred, and why?
The difference is in the type that is inferred for T: in add1 it is the component type of the first collection (Driver), in add2 it's the component type of the second collection (Person).
In this case T is not used in the method body, so there's no visible difference.
If A is a supertype of B, then B extends A, so there is no difference between the two versions.
Note that you can also use both super and extends:
public static <T> void add3(final Collection<? extends T> drivers, final Collection<? super T> persons) {
persons.addAll(drivers);
}

Categories