Почему T ограничено объектом в подписи Collections.max()?

Просто прошел через реализацию класса Java 7 java.util.Collections и увидел что-то, чего я не понимаю. В сигнатуре функции max, почему T ограничен Object?

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) {
    Iterator<? extends T> i = coll.iterator();
    T candidate = i.next();

    while (i.hasNext()) {
        T next = i.next();
        if (next.compareTo(candidate) > 0)
            candidate = next;
    }
    return candidate;
} 

max, кажется, работает нормально, если граница Object опущена.

public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll) {
    Iterator<? extends T> i = coll.iterator();
    T candidate = i.next();

    while (i.hasNext()) {
        T next = i.next();
        if (next.compareTo(candidate) > 0)
            candidate = next;
    }
    return candidate;
}

Существуют ли в действительности ситуации, когда граница имеет значение? Если да, укажите конкретный пример.

Ответ 1

Оба имеют те же границы, но есть тонкая разница.

 <T extends Object & Comparable<? super T>> 

Это приведет к тому, что T станет Object при стирании.

 <T extends Comparable<? super T>>

Это приведет к тому, что T станет Comparable при стирании.


В этом случае это делается, потому что .max предшествует Java 5. Мы можем видеть в этой ссылке. Joachim любезно предоставил, что подпись .max в Java 1.4.2:

public static Object max(Collection coll)

Если бы мы использовали <T extends Comparable<? super T>> как оценку, наша подпись была бы

public static Comparable max(Collection coll)

Что нарушит API. Мне удалось найти эту страницу, в которой обсуждается преобразование старых API в общие, и в качестве конкретного примера он дает .max.

Здесь они объясняют, почему max определяется следующим образом:

Вам также необходимо убедиться, что пересмотренный API сохраняет двоичную совместимость со старыми клиентами. Это означает, что стирание API должно быть таким же, как и оригинальный, негенерированный API. В большинстве случаев это естественно, но есть некоторые тонкие случаи. Мы рассмотрим один из самых тонких случаев, с которыми мы столкнулись, метод Collections.max(). Как мы видели в разделе More Fun with Wildcards, правдоподобной сигнатурой для max() является:

public static <T extends Comparable<? super T>> T max(Collection<T> coll) Это хорошо, за исключением того, что стирание этой сигнатуры: public static Comparable max(Collection coll), которая отличается от исходной подписи max(): public static Object max(Collection coll)

Можно было бы указать эту подпись для max(), но она не была выполнена, и все старые файлы двоичных классов, которые вызывают Collections.max(), зависят от подписи, которая возвращает Object.