Here is the case, I have two classes A, B, and a generic interface C
Class A implements Comparable<A> {...}
interface C<T> {...}
//this class is not longer generic type, I do not know if this matter.
Class B extends A implements C<A> {...}
Then, at other class, I got a B List and sort it as follow
List<B> list = new ArrayList<B>();
Collections.sort(list);
This works perfectly, but now I would like to change the list of B to the generic interface C, so that it can be more general.
List<C<A>> list = new ArrayList<C<A>>();
Collections.sort(list);
This time I got the Error as follow:
Bound mismatch: The generic method sort(List<T>) of type Collections is not
applicable for the arguments (List<C<A>>). The inferred type C<A> is not a
valid substitute for the bounded parameter <T extends Comparable<? super T>>
I have tried the following modifications (of course does not work):
change C to interface C<T> extends Comparable<T>{...}
change B to class B extends A implements C<A>, Comparable<T> {...}
Can anybody help me?
change C to interface C extends Comparable{...}
Class B extends A implements C {...}
As you would have already seen from the error messages, these two won't work together as there will be a conflict in B's definition w.r.t to Comparable<A> and Comparable<C<A>>.
Since A is already implementing Comparable<A>, you can achieve the following
List<C<A>> list = new ArrayList<C<A>>();
Collections.sort(list);
by defining a Comparator for C<A> as follows:
class CTComparator<T> implements Comparator<C<T>>
{
#Override
public int compare(C<T> o1, C<T> o2)
{
return 0;
}
}
and then applying the sort method with this comparator:
List<C<T>> list = new ArrayList<C<T>>();
Collections.sort(list, comparator);
Since C<A> is not having the visibility of the Comparator defined in A hence it's complaining. Define a new comparator of C<A> as blow, it should be fine then.
List<C<A>> list = new ArrayList<C<A>>();
Collections.sort(list, new Comparator<C<A>>() {
#Override
public int compare(C<A> o1, C<A> o2) {
//implement the comarison
return 0;
}
});
If you expect C<T> to be generically comparable based on the type it contains, you should make it comparable on itself (C<T>, not T), but bound its value type to those that implement Comparable. Something like this:
public class C<T extends Comparable<? super T>> extends Comparable<C<T>> {
private final T value;
#Override
public int compareTo(C<T> that) {
return this.value.compareTo(that.value);
}
}
This only makes sense for some containers, such as those that simply wrap a value.
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
When trying to compare a generic type in the form
Class<T> implements Comparable<T> {
public int compareTo(T other){
this.T < other
}
}
does not work for me but when using
Class<T extends Comparable<T>>{
T.compareTo(other.T)
}
does work. I have been unable to deciper why I can't compare T directly using the first example
In your first example:
class Foo<T> implements Comparable<T> {
you're saying that Foo objects are comparable. In your second example:
class Foo<T extends Comparable<T>>{
you're saying that whatever T, is, it's comparable.
Then, in the body of your code, you try to compare things of type T -- in the first case, you have no guarantee that they're comparable, in the second, you do.
I hope these two exmaples will cast some light on your problem:
class Foo<T> implements Comparable<T> {
#Override
public int compareTo(T o) {
// We don't know anything about T
return hashCode() - o.hashCode();
}
}
class Boo<T extends Comparable<? super T>> implements Comparable<T> {
private T instance;
#Override
public int compareTo(T o) {
// We know that T implements Comparable<? super T>
return instance.compareTo(o);
}
}
In first case with Foo, you don't know anything about type T, so you can't do much in your compareTo() method.
However, in Boo, T is required to implement Comparable<? super T> (if you don't know what wildcards are, just think there is simply Comparable<T>), so you can call t.compareTo(anotherT). More about bounded type parameters.
EDIT: (wildard explained)
Consider following code:
class Car implements Comparable<Car> { ... }
class SportCar extends Car { ... }
Now call sportCar1.compareTo(SportCar2) is perfectly legal. However, without the wildcard,
Bar<SportCar> is a cpompile error!
Why? Because SportCar doesn't implement Comparable<SportCar>. And you require T to implement Comparable<T>, and in this case T is SportCar.
But SportCar implements Comparable<Car> and Car is a supertype of SportCar. So you want to say something like "T can be compared to T or any supertype of T" (like in this case SportCar can be compared to any Car).
And that what the wildcard is for (among many other things). Hope this helps.
I have this interface
public interface IDataPoint<T> extends Comparable<T> {
public T getValue();
}
and this implementation...
public class IntegerDataPoint implements IDataPoint<Integer> {
// ... some code omitted for this example
public int compareTo(Integer another) {
// ... some code
}
}
and another class...
public class HeatMap<X extends IDataPoint<?> {
private List<X> xPoints;
}
Now I would like to use Collections.max (and similar) on the xPoints list, but that does not work, probably because I got my generics all messed up.
Any suggestions how this could be solved (without a Comparator)?
Collections.max(xPoints);
gives me this error:
Bound mismatch: The generic method max(Collection<? extends T>) of type Collections is not applicable for the arguments (List<X>). The inferred type X is not a valid substitute for the bounded parameter <T extends Object & Comparable<? super T>>
The problem is that Collections.max(Collection<? extends T>) wants the T's to be comparable to themselves not some other type.
In your case IntegerDataPoint is comparable to Integer, but not IntegerDataPoint
You cannot easily fix this because IntegerDataPoint is not allowed to implement Comparable<Integer> and Comparable<IntegerDataPoint> at the same time.
I want to have an interface A parameterised by T A<T>, and also want every class that implements it to also implement Comparable (with T and its subtypes). It would seem natural to write interface A<T> extends Comparable<? extends T>, but that doesn't work. How should I do it then?
When Comparable<? extends T> appears it means you have an instance of Comparable that can be compared to one (unknown) subtype of T, not that it can be compared to any subtype of T.
But you don't need that, because a Comparable<T> can compare itself to any subtype of T anyway, e.g. a Comparable<Number> can compare itself to a Comparable<Double>.
So try:
interface A<T> extends Comparable<T> {
// ...
}
or
interface A<T extends Comparable<T>> extends Comparable<A<T>> {
// ...
}
depending on whether you need to be able to compare instances of T in order to implement your compareTo method.
If you use comparable you do not need to specify the possibility for subtypes in the compare function, it is by nature possible to pass in any subtype of an object X into a method that declared a parameter of class X. See the code below for more information.
public interface Test<T> extends Comparable<T> {
}
class TestImpl implements Test<Number> {
#Override
public int compareTo(final Number other) {
return other.intValue() - 128;
}
}
class TestMain {
public static void main(final String[] args) {
TestImpl testImpl = new TestImpl();
testImpl.compareTo(Integer.MIN_VALUE);
}
}
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