9

Suppose I have a method called foo taking 2 Object as parameter. Both objects are of the same type and both implements comparable interface.

void foo(Object first, Object second){

    if (!first.getClass().isInstance(second))   //first and second of the same type
        return;

    Comparable firstComparable = (Comparable)first;  //WARNING
    Comparable secondComparable = (Comparable)second;  //WARNING

    int diff = firstComparable.compareTo(secondComparable);  //WARNING
}

The first 2 warning are:

Comparable is a raw type. References to generic type Comparable should be parameterized

The last warning:

Type safety: The method compareTo(Object) belongs to the raw type Comparable. References to generic type Comparable should be parameterized

How could I refactor my code in order to remove these warnings?

EDIT: Can I do that without changing foo method's signature?

Heisenbug
  • 38,762
  • 28
  • 132
  • 190
  • 1
    @overbose:why not take change function parameter's from object to comparable ? – Emil Aug 10 '11 at 09:48
  • @Emil cause the same Warning `Comparable is a raw type` – oliholz Aug 10 '11 at 09:55
  • @0verbose:why do you want to get rid of the warning ? Even if you use generics still it is only a syntactic sugar and casting will any how take place.Why don't you simply suppress the warnings ? – Emil Aug 10 '11 at 10:21
  • @Emil: it was just curiosity. Even with the warning the code works fine. – Heisenbug Aug 10 '11 at 10:23

5 Answers5

15

You have to tell the compiler that they are the same type and comparable. If you can't change the signature you can add a method for backward compatibility.

@SuppressWarnings("unchecked")
static void foo(Object first, Object second) {
    foo((Comparable) first, (Comparable) second);
}

static <T extends Comparable<T>> void foo(T first, T second){
    int diff = first.compareTo(second); // no warning.
}
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • I can't change foo method signature. Is it impossible to achieve that without changing foo's signature? – Heisenbug Aug 10 '11 at 09:54
  • You have to have some way of telling the compiler what type the first and second are. You can't change this without changing the signature. If you can't change the signature you can use more than one method – Peter Lawrey Aug 10 '11 at 10:04
  • Ok..I get it. thanks for the answer..anyway seems that is not be possible to do what I want with no warnings at all. – Heisenbug Aug 10 '11 at 10:22
  • The warnings are expected as the compiler cannot determine if the casting you are doing is safe. Only you can tell it is safe by using the right signature. – Peter Lawrey Aug 10 '11 at 10:38
3

Without changeing Signature you can do

    void foo(Object first, Object second){

        if (!first.getClass().isInstance(second)) 
            return;

        Comparable<Object> firstComparable = (Comparable<Object>)first;  
        Comparable<Object> secondComparable = (Comparable<Object>)second; 

        int diff = firstComparable.compareTo(secondComparable);  
    }

But you still got :
Type safety: Unchecked cast from Object to Comparable<Object>

but no Comparable is a raw type. References to generic type Comparable<T> should be parameterized
and no Type safety: The method compareTo(Object) belongs to the raw type Comparable. References to generic type Comparable<T> should be parameterized

oliholz
  • 7,447
  • 2
  • 43
  • 82
1

You have to do use Comparable<Type> where Type is the object that is implementing Comparable.

First, why are your method parameters instance of Objects? If you are sure the types of parameters are same, you should use the specific class as the parameter. If you can have an hierarchy of classes, have the class highest in the hierarchy. Having Object to acheive general functionality is never a good idea.

Nivas
  • 18,126
  • 4
  • 62
  • 76
  • I know that type is Double or Integer, or something else implementing Comparable interface, but I don't know which particular type. Specific type is known only at runtime. – Heisenbug Aug 10 '11 at 09:57
  • You either have to change your method's signature as in @Peter Lawrey's answer, or live with the warning... – Nivas Aug 10 '11 at 10:01
1

EDIT: Since you said you can't change the method's signature, then you really can't get away without an unsafe (to the compiler) cast, and a @SuppressWarnings:

@SuppressWarnings("unchecked")
public void foo(final Object first, final Object second) {
    if (!first.getClass().isInstance(second)) // first and second of the
        return;

    Comparable<Object> firstComparable = (Comparable<Object>) first;
    Comparable<Object> secondComparable = (Comparable<Object>) second;
    int diff = firstComparable.compareTo(secondComparable);
}
Alistair A. Israel
  • 6,417
  • 1
  • 31
  • 40
0

Add @SuppressWarnings annotation.

@SuppressWarnings("unchecked")
void foo(Object first, Object second){

    if (!first.getClass().isInstance(second))   //first and second of the same type
        return;

    Comparable firstComparable = (Comparable)first;  //WARNING
    Comparable secondComparable = (Comparable)second;  //WARNING

    @SuppressWarnings("unused")
    int diff = firstComparable.compareTo(secondComparable);  //WARNING
}
Ondrej Sotolar
  • 1,352
  • 1
  • 19
  • 29