Reputation: 3168
I want to compare two arguments in less method which are of type Comparable. But if I use comapreTo it is giving me error in type casting:
private boolean less(Comparable<T> u, Comparable<T> v) {
return u.compareTo(v) < 0;
}
I fixed the issue by type casting the argument passed into compareTo. But still it is giving me warning (Type safety: Unchecked cast from Comparable to T). Why is it so. Am I doing something wrong. What is the best way to achieve this.
private boolean less(Comparable<T> u, Comparable<T> v) {
return u.compareTo((T) v) < 0;
}
Upvotes: 0
Views: 172
Reputation: 122499
Since u
has type Comparable<T>
, u.compareTo()
takes a T
. You're passing it v
, a Comparable<T>
, which is not compatible.
You might be assuming in your mind that a type that implements Comparable
is comparable to itself. But there is no such requirement on a technical level. It's perfectly legal for me to make a type Foo
, that is Comparable<Bar>
, i.e. it compares to Bar
, where Foo
and Bar
are completely unrelated. Trying to pass a Foo
into a Foo
object's compareTo
will crash.
If you want to make a constraint that the two arguments are of the same type which is comparable to itself, you would do something like
private <T extends Comparable<? super T>> boolean less(T u, T v) {
return u.compareTo(v) < 0;
}
However, for the purposes of this function, the constraint that the two arguments are of the same type is not technically necessary (although it should be true in all normal use cases). And in generics we always want to use the least restrictive bound possible, which is, as other answers have mentioned,
private <T> boolean less(Comparable<T> u, T v) {
return u.compareTo(v) < 0;
}
In your comments, you mentioned you are comparing elements from a Comparable<T>[]
. That is not a type of array that allows you to compare elements from. You just know that it's an array of elements that are comparable to a certain T
, but not comparable to themselves. Much more useful would be to have a T[]
, where T
has a bound that it is comparable to itself:
class Whatever<T extends Comparable<? super T>> {
//...
T[] yourArray;
}
Upvotes: 1
Reputation: 3079
The initial error is correct, and the warning is correct to: your trick is very unsafe: you can't cast v to T.
Because your method takestwo parameters u and v, each one is an instance of a class, which implements compareTo ( some instance of T).
precisely: u can compare to T, v can compare to T.
But, inside, you want to compare u and v. There is absolutely no garantee you can do it.
This, for example, is correct:
private static <X> boolean less(Comparable<X> u, X v)
{
return u.compareTo(v) < 0;
}
Upvotes: 1