2008-11-05 4 views
2

Я хотел бы удалить все «непроверенные» предупреждения из этого общего метода полезности (часть более крупного класса с рядом аналогичных методов). В крайнем случае я могу использовать @SuppressWarnings («unchecked»), но мне интересно, могу ли я правильно использовать дженерики, чтобы избежать предупреждения.Использование общих параметров со статическим методом compareObject

Метод предназначен для того, чтобы вызывающие могли сравнивать два объекта путем прохождения через compareTo, за исключением того, что если объект является строкой, он делает это нечувствительным к регистру образом.

public static int compareObject(Comparable o1, Comparable o2) 
{ 
    if ((o1 instanceof String) && (o2 instanceof String)) 
     return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase()); 
    else 
     return o1.compareTo(o2); 
} 

Это была моя первая (неправильная) попытка решения. Параметры работают отлично, но линия o1.compareTo (o2) имеет ошибку компиляции «Метод CompareTo (захват # 15-о?) В типе Сравнительное не применяется для аргументов (Сопоставимые».

public static int compareObject(Comparable<?> o1, Comparable<?> o2) 
{ 
    if ((o1 instanceof String) && (o2 instanceof String)) 
     return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase()); 
    else 
     return o1.compareTo(o2); 
} 
?

Любые предложения

+0

Как правило, вы, вероятно, должны использовать compareToIgnoreCase вместо преобразования обеих строк в верхний регистр. У вашего метода могут быть тонкие ошибки с интернационализацией (см. Документацию toUpperCase). – 2008-11-05 21:37:59

+0

Отличная точка - изменится! – 2008-11-05 22:06:51

ответ

2

Я просто попытался это:?.

public static <T extends Comparable> int compareObject(T o1, T o2) { 
    if ((o1 instanceof String) && (o2 instanceof String)) 
     return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase()); 
    else 
     return o1.compareTo(o2); 
} 

Он компилирует, но дает предупреждение о непроверенной броске при вызове compareTo().
Я попытался изменить его

public static <T extends Comparable<T>> int compareObject(T o1, T o2) { 

и проверки строк не удалось собрать ("неконвертируемых типов: Найдено: T, требуется: String"). Я думаю, что это должно быть близко.


EDIT: Как было отмечено в комментариях, это bug in javac. Вторая форма действительно правильная, но в настоящее время она не будет компилироваться. Сумасшедший, как это может выглядеть, это код, который работает без предупреждений:

public static <T extends Comparable<T>> int compareObject(T o1, T o2) { 
    if (((Object) o1 instanceof String) && ((Object) o2 instanceof String)) 
     return ((String) (Object)o1).toUpperCase().compareTo(((String) (Object)o2).toUpperCase()); 
    else 
     return o1.compareTo(o2); 
} 

Как вы можете видеть, единственное различие все избыточными бросает в Object.

+0

Я не получаю эту ошибку с последней подписью. Какую версию javac вы используете? – erickson 2008-11-05 21:40:59

+0

Java 6. Я получаю красные squigglies в NetBeans, и я просто получил ту же ошибку, когда я попробовал ее из командной строки. – 2008-11-05 21:47:35

-1

ли вы проверить следующие

public static <T> int compareObject(Comparable<T> o1, Comparable<T> o2) 
{ 
    if ((o1 instanceof String) && (o2 instanceof String)) 
     return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase()); 
    else 
     return o1.compareTo(o2); 
} 

Я думаю, что он должен работать правильно

+0

Я только что проверил, и это не так. – 2008-11-05 21:21:39

1

Вот то, что вы ищете:

public static <T extends Comparable<T>> int compareObject(T o1, T o2) { 
    if ((o1 instanceof String) && (o2 instanceof String)) 
     return ((String) o1).toUpperCase().compareTo(((String) o2).toUpperCase()); 
    else 
     return o1.compareTo(o2); 
} 
1

Я надеюсь, что вы знаете, что многие подходы здесь делать изменения семантики метода. С оригинальным способом можно сравнить объекты разных типов, если они позволяют это, но с

public static <T extends Comparable<T>> int compareObject(T o1, T o2) 

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

public static int compareObject2(Comparable<Object> o1, Comparable<Object> o2) { 
    if (((Object) o1 instanceof String) && ((Object) o2 instanceof String)) 
     return ((String) (Object)o1).toUpperCase().compareTo(((String) (Object)o2).toUpperCase()); 
    else 
     return o1.compareTo(o2); 
} 

(я вставил обходной путь для указанного JAVAC ошибки.) Но это не повышает безопасность типа или что-нибудь, так что в данном случае это, вероятно, лучше использовать более понятные Некоммерческий общий метод и жить с @SuppressWarnings("unchecked"). Существует такая вещь, как чрезмерное использование дженериков.

0

Что можно сказать о следующем:

public static <T extends Comparable<T>> int compareObjects(T o1, T o2) 
    { 
    return o1.compareTo(o2); 
    } 

    public static int compareObjects(String o1, String o2) 
    { 
    return o1.compareToIgnoreCase(o2); 
    } 

Недостаток заключается в том, что, когда вызов compareObjects() с объектами, которые случаются быть струнные, компилятор будет связать ваш вызов первой функции, и вы будете в конечном итоге с с учетом регистра.

Смежные вопросы