Java interface extends Comparable - java

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);
}
}

Related

Difference between generics <T extends Number & Comparable<T>> and T extends Comparable<? extends Number>

Can someone explain the difference between <T extends Number & Comparable<T>> and T extends Comparable<? extends Number>?
These look similar to me and both of them compiles fine for sub classes type. The invalid type args shows below error
Type parameter is not within bound parameter;should implement
'java.lang.Number'
and
Type parameter is not within bound parameter; should extend
'java.lang.Comparable>'
respectively.
You won't be able to use:
Comparable<? extends Number>
because the only methods defined by Comparable are consumers (in the sense of PECS): it needs to accept instances of type ? extends Number into its compareTo method - and there is no type which satisfies that bound safely.
Integer is a Comparable<? extends Number>, but so is Double. Thus, you can't safely call instance1.compareTo(instance2) because it would fail if these instances are concretely Integer and Double respectively, since Integer.compareTo can only accept Integer parameters.
As such, the compiler prevents you from calling this method in the first place.
Option 1:
public class A <T extends Number & Comparable<T>>{}
Your Generic Parameter should extend Number and implements Comparable,
which means class A is a Number and Comparable.
Option 2:
public class B <T extends Comparable<? extends Number>>{}
T is Comparable on Numbers(can compare Number only) but doesn't have to be a Number, unlike option 1
I will explain by example:
A
public class A <T extends Number & Comparable<T>>{}
B
public class B <T extends Comparable<? extends Number>>{}
IntegerWrapper(Option 2)
public class IntegerWrapper implements Comparable<Integer> {
Integer number;
public IntegerWrapper(int number) {
this.number = number;
}
#Override
public int compareTo(Integer o) {
return number.compareTo(o);
}
}
GenericsTest
public class GenericsTest {
public static void main(String args[]){
A myA = new A<Integer>();
B myB = new B<IntegerWrapper>();
}
}
I think option 1 is what you are looking for, because i can't think of many useful scenarios for Option 2(Maybe there is...)

Java Comparable for Generic Types

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.

Java Collection compare generic class that extends interface that extends comparable

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 limit type T that is a class which implements the Comparable<T> interface in a generic class

I defined a generic class A<T> in Java, but I want to limit the type T such that it is a class which implements the Comparable<T> interface. What should i do?
I think you just want:
class A<T extends Comparable<T>>
{
}
Or possibly:
class A<T extends Comparable<? super T>>
{
}
The latter is slightly more flexible - it allows for things like:
class Foo implements Comparable<Object>
{
}
A<Foo> a = new A<Foo>();
That's fine if you just want A to be able to compare values of type T.
public class A<T extends Comparable<? super T>>{
...
}
this allows you to use subclasses of classes that implement comparable
You can put an upper bound on T:
public class A<T extends Comparable<T>> {
//...
}
Class A <T implements ComparableInterface>

question about interfaces and generics in Java: type mismatch error

Suppose I have the following interface:
public interface Interface<T extends Number>{
public Vector<Interface<T>> getVector();
}
and the following class implementing that interface:
public abstract class C<T extends Number> implements Interface<T>{
private Vector<C<T>> vector;
public Vector<Interface<T>> getVector(){ //errror
return this.vector;
}
}
Why is not legal returning a Vector<C<T>> meanwhile is legal ( obviously) returning a Vector<Interface<T>>. C is actually implementing Interface, so it should be possible, right? What am I missing?
EDIT:
why this work for non generics interface? Is this actually a generic related problem?
public interface Interface{
public Interface getVector();
}
public abstract class C implements Interface {
private C;
public Interface getVector(){ //errror
return this.c;
}
}
Because the Vector is explicitly made up of Interface<T>, not things that extend Interface<T>, I believe this would work if you changed the definition to
public Vector<? extends Interface<T>> getVector();
The problem is that for some V implements T or V extends T that Foo<V> is not a supertype of Foo<T>. The compiler does not test inheritance on the generic arguments unless you explicitly indicate that extension point.
Using Vector<? extends Interface<T>> means "allow any class that implements or extends Interface<T>, whereas Vector<Interface<T>> means a vector consisting only of Interface<T> items.
Perhaps it's more concrete to consider that List<Integer> is not an acceptable replacement for List<Number> despite Integer extending Number for precisely the same reason.
update:
I tested this and the following compiles without any errors or warnings
interface Interface<T extends Number>{
public Vector<? extends Interface<T>> getVector();
}
abstract class C<T extends Number> implements Interface<T>{
private Vector<C<T>> vector;
public Vector<? extends Interface<T>> getVector(){
return this.vector;
}
}
It's the way generics work. They are not "covariant": if you have class AClass and its subclass SubAClass, Vector<SubAClass> is not a subclass of Vector<A>. (Note however that SubAClass[] is a subclass of AClass[].)
EDIT:
The seemingly obvious:
public ArrayList<Object> blah() {
return new ArrayList<String>();
}
won't compile because ArrayList<String> is not a subclass ArrayList<Object>. So in your case you can't return a Vector<C<T>> instance for a Vector<Interface<T>>.

Categories