What does self comparable interface do in Collections Class? - java

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.

Related

Why Collections.min(Arrays.asList(new Base(), new Base())) gives a strange compile error (Eclipse)?

Why for class Base I get a strange compile error (Eclipse):
Collections.min(Arrays.asList(new Base(), new Base()));
fails with compile error:
Type mismatch: cannot convert from List<Base> to Collection<? extends T>
- The method min(Collection<? extends T>) in the type Collections is not applicable for the arguments (List<Base>)
P.S. I understand that class Base shall be Comparable, but the compiler complains not about that... min expects Collection as its argument, and Arrays.asList returns List, List is a Collection.
The error above is gone if I make class Base implement Comparable, but anyway the error is strange.
The reason that it compiles after having Base implement Comparable is because of Collections#min's signature:
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)
You can see that T must be Comparable and will not compile otherwise.
Another solution is to pass an explicit Comparator to the overloaded method:
public static <T> T min(Collection<? extends T> coll, Comparator<? super T> comp)

Comparable<? super T> vs. Comparable<T>

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.

Is there a need to use bounded wildcard generics in a passthrough method?

I know that in the following method in Collection<E>:
public void addAll(Collection<? extends E> subcollection);
We use Collection<? super E> there to allow a collection that solely exists of sub-elements, example:
List<Drivable> drivables = new ArrayList<>();
List<Car> cars = new ArrayList<>();
//we need the wildcard here, because of the following line:
drivables.addAll(cars);
However, are such bounded wildcards needed in my following method?
public static <E> Collection<E> requireNonEmpty(final Collection<E> collection) throws NoSuchElementException {
if (collection.isEmpty()) {
throw new NoSuchElementException("collection must be non-empty");
}
return collection;
}
This uses a similar idiom as Objects.requireNonNull(T object), which actually returns the T object.
So, is there any benefit (or is it even wrong?) to write my method as the following?
public static <E> Collection<? super E>
requireNonEmpty(final Collection<? extends E> collection);
The use of Collection<? extends E> subcollection makes the passed parameter a universal donor - i.e. it can be read from with freedom.
You do not need to read objects from the passed collection so you do not need any wildcards.
Incidentally using Collection<? super E> subcollection makes it a universal recipient - i.e. you can add to it.
See When to use extends and super for a clear introduction.
Also a good answer covering this Generic lower unbound vs upper bounded wildcards.

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

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.

Why no bounded wildcard in input parameters of synchronizedCollection() static factory method?

I was going through the Java tutorial and stumbled on something which I did not understand. In the Collections trail, they talk about Wrapper implementations, there I notice two static factory methods -
public static <T> Collection<T> synchronizedCollection(Collection<T> c);
public static <T> Collection<T> unmodifiableCollection(Collection<? extends T> c);
I am wondering why does synchronized wrappers don't use bounded wildcards? i. e. Why is the signature of synchronizedCollection not the following?
public static <T> Collection<T> synchronizedCollection(Collection<? extends T> c);
Collection<? extends T> c with that you can only get stuffs but cannot add to it, which makes sense in case of unmodifiableCollection, for the method the argument should only act as producer. But in case of synchronizedCollection, it's synchronized but still modifialbe, it should also be able to add and remove, so it has to be Collection<T> c, it should act as both producer and consumer.
This might be helpful to know about What is PECS (Producer Extends Consumer Super)?
I think unmodifiableCollection is in the wrong. Both methods intend to wrap Collection<T> as Collection<T>, there's no reason to change the type argument.
Sure it is more flexible to take in a Collection<? extends T>, so caller can request to convert a Collection<Integer> to an unmodifiable Collection<Integer> or Collection<Number> or Collection<Object> etc. But who needs that? A readonly Collection<Integer> is in every way better than Collection<Number> anyway.
If the input type itself contains wildcard, e.g.
Collection<? extends Number> someNumbers = ...;
with unmodifiableCollection(Collection<? extends T>) we can do
Collection<Number> readonlyNumbers
= unmodifiableCollection(someNumbers);
Collection<Object> readonlyObjects
= unmodifiableCollection(someNumbers);
but with unmodifiableCollection2(Collection<T>) we must
Collection<? extends Number> readonlyNumbers
= unmodifiableCollection2(someNumbers);
Collection<? extends Object> readonlyObjects
= unmodifiableCollection2(someNumbers);
the 2nd version is messier, but it is probably more politically correct.

Categories

Resources