Использование общих параметров со статическим методом compareObject - PullRequest
2 голосов
/ 06 ноября 2008

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

Этот метод предназначен для того, чтобы вызывающие абоненты могли сравнивать два объекта, передавая метод 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-из?) Типа Comparable не применим для аргументов (Comparable».

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

Есть предложения?

Ответы [ 5 ]

2 голосов
/ 06 ноября 2008

Я только что попробовал это:

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, требуется: строка»). Я думаю, что это должно быть близко, хотя.


РЕДАКТИРОВАТЬ: Как указано в комментариях, это ошибка в 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.

1 голос
/ 06 ноября 2008

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

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"). Существует такая вещь, как чрезмерное использование дженериков.

1 голос
/ 06 ноября 2008

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

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);
}
0 голосов
/ 20 марта 2009

А как насчет следующего:

  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() с объектами, которые оказались Strings, компилятор свяжет ваш вызов с первой функцией, и вы получите сравнение с учетом регистра.

0 голосов
/ 06 ноября 2008

Тестировали ли вы следующее?

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...