Java: удаление Comparable - это предупреждение необработанного типа

Предположим, у меня есть метод под названием foo, принимающий 2 объекта в качестве параметра. Оба объекта относятся к одному типу и реализуют сопоставимый интерфейс.

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
}

Первые 2 предупреждения:

Comparable - это сырой тип. Ссылки на общий тип Comparable должны быть параметризованы.

Последнее предупреждение:

Безопасность типов: метод compareTo (Object) принадлежит к необработанному типу Comparable. Ссылки на общий тип Comparable должны быть параметризованы.

Как мне провести рефакторинг своего кода, чтобы убрать эти предупреждения?

РЕДАКТИРОВАТЬ: Могу ли я сделать это, не меняя подпись метода foo?


person Heisenbug    schedule 10.08.2011    source источник
comment
@overbose: почему бы не взять параметр функции изменения с объекта на сопоставимый?   -  person Emil    schedule 10.08.2011
comment
@Emil вызывает такое же предупреждение Comparable is a raw type   -  person oliholz    schedule 10.08.2011
comment
@ 0verbose: почему вы хотите избавиться от предупреждения? Даже если вы используете дженерики, это всего лишь синтаксический сахар, и приведение типов будет происходить каким-либо образом. Почему бы вам просто не подавить предупреждения?   -  person Emil    schedule 10.08.2011
comment
@ Эмиль: это было просто любопытство. Даже с предупреждением код работает нормально.   -  person Heisenbug    schedule 10.08.2011


Ответы (5)


Вы должны сообщить компилятору, что они одного типа и сопоставимы. Если вы не можете изменить подпись, вы можете добавить метод обратной совместимости.

@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.
}
person Peter Lawrey    schedule 10.08.2011
comment
Я не могу изменить подпись метода foo. Разве этого нельзя добиться без изменения подписи foo? - person Heisenbug; 10.08.2011
comment
У вас должен быть способ сообщить компилятору, какой тип у первого и второго. Вы не можете изменить это без изменения подписи. Если вы не можете изменить подпись, вы можете использовать более одного метода - person Peter Lawrey; 10.08.2011
comment
Хорошо, я понимаю. спасибо за ответ .. в любом случае кажется, что невозможно делать то, что я хочу, вообще без предупреждений. - person Heisenbug; 10.08.2011
comment
Предупреждения ожидаются, поскольку компилятор не может определить, безопасно ли выполняемое вами преобразование. Только вы можете сказать, что это безопасно, используя правильную подпись. - person Peter Lawrey; 10.08.2011

Без изменения подписи вы можете сделать

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

Но у вас все еще есть:
Type safety: Unchecked cast from Object to Comparable<Object>

но нет Comparable is a raw type. References to generic type Comparable<T> should be parameterized
и нет Type safety: The method compareTo(Object) belongs to the raw type Comparable. References to generic type Comparable<T> should be parameterized

person oliholz    schedule 10.08.2011
comment
Вы можете проверить состав с помощью if(Comparable.class.isAssignableFrom( first.getClass() )) - person oliholz; 10.08.2011

Вы должны использовать Comparable<Type>, где Тип - это объект, реализующий Comparable.

Во-первых, почему параметры вашего метода являются экземпляром Objects? Если вы уверены, что типы параметров совпадают, вы должны использовать конкретный класс в качестве параметра. Если у вас может быть иерархия классов, сделайте класс наивысшим в иерархии. Иметь Object для достижения общей функциональности - плохая идея.

person Nivas    schedule 10.08.2011
comment
Я знаю, что это тип Double или Integer, или что-то еще, реализующее интерфейс Comparable, но я не знаю, какой именно тип. Конкретный тип известен только во время выполнения. - person Heisenbug; 10.08.2011
comment
Вам либо нужно изменить подпись своего метода, как в ответе @Peter Lawrey, либо жить с предупреждением ... - person Nivas; 10.08.2011

РЕДАКТИРОВАТЬ: Поскольку вы сказали, что не можете изменить подпись метода, тогда вы действительно не можете обойтись без небезопасного (для компилятора) приведения и @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);
}
person Alistair A. Israel    schedule 10.08.2011
comment
Я бы хотел это сделать, но, как я уже сказал, мне не следует изменять сигнатуру метода foo. - person Heisenbug; 10.08.2011

Добавьте аннотацию @SuppressWarnings.

@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
}
person Ondrej Sotolar    schedule 10.08.2011
comment
Это ничего не меняет ... просто подавляет вывод предупреждений. - person Heisenbug; 10.08.2011