2012-04-25 2 views
6

Это реализуется следующим образом (jdk1.6.0_31):Java: о реализации Коллекции ReverseComparator

private static class ReverseComparator<T> 
implements Comparator<Comparable<Object>>, Serializable { 

// use serialVersionUID from JDK 1.2.2 for interoperability 
private static final long serialVersionUID = 7207038068494060240L; 

    public int compare(Comparable<Object> c1, Comparable<Object> c2) { 
     return c2.compareTo(c1); 
    } 

    private Object readResolve() { return reverseOrder(); } 
} 

Почему она не может быть реализован следующим образом:

private static class ReverseComparator<T extends Comparable<T>> 
implements Comparator<T>, Serializable { 

// use serialVersionUID from JDK 1.2.2 for interoperability 
private static final long serialVersionUID = 7207038068494060240L; 

    public int compare(T c1, T c2){ 
     return c2.compareTo(c1); 
    } 
    ... 
} 

Является ли это просто стиль , или есть какая-то более глубокая причина?

EDIT: исходный код показан с помощью Sun/Oracle jdk ((jdk1.6.0_31)).

+0

Где именно находится этот код? Я не нахожу его в JDK, но есть много других мест. До сих пор никто не использовал дженерики. –

+0

Я нашел его в jdk1.6.0_31, src.zip. – shrini1000

+0

Но можете ли вы сказать мне, где именно? В каком классе? –

ответ

1

Я считаю, что все это связано с намерением сделать ReverseComparator объектом singlenton. Поскольку экземпляр singlenton должен быть определен в статическом контексте, нет смысла использовать какие-либо общие типы.

static final ReverseComparator REVERSE_ORDER = new ReverseComparator(); 

Этот код генерирует предупреждение о необработанном типе.

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

Запуск декомпилятора Java над вашей реализацией и над реализацией Oracle создает одинаковые коды байтов исходного типа.

public int compare(java.lang.Comparable, java.lang.Comparable 
public int compare(java.lang.Object, java.lang.Object); 

В конце концов, когда компаратор подвергается через открытый интерфейс класса Collections в методе reverseOrder(), невозможно избежать литья и непроверенное предупреждение. Но мы все уверены, что это не может потерпеть неудачу, независимо от того, какие из них связаны.

Итог, ИМХО Я думаю, единственная причина, по которой это было реализовано, поскольку это было связано с ясностью кода или с желанием не усложнять вещи больше, чем необходимо, если, в любом случае, неконтролируемое предупреждение не может быть предотвращено , Но эй, это не первый раз, когда я ошибаюсь ;-)

+0

Я согласен с вами в том, что дальнейшее обобщение не требуется, потому что класс используется в частном порядке. На самом деле, я не думаю, что любое обобщение этого возможно, потому что в Java достаточно класс, который реализует Comparable, чтобы он мог использоваться как аргумент типа в параметризованном типе. Поэтому я чувствую, что больше похож на ненужный остаток от предыдущего кода. – shrini1000

1

Просто угадать, но он хранится в статическом поле

static final ReverseComparator REVERSE_ORDER 
      = new ReverseComparator(); 

так что ваша версия будет генерировать предупреждение "сырьевых типов.

+0

Ну, я получаю это предупреждение с помощью ReverseComparator Java (так как он объявляет «T» в своем определении), если я скопирую этот класс в своем классе и статично его стану. – shrini1000

+0

Хмм, в моем источнике это просто 'частный статический класс ReverseComparator' (нет' T') – artbristol

+0

это jdk1.6.0_31 или какая-то другая версия? – shrini1000

1

Я смотрю на Oracle 1.6.0_26, но я вижу тот же код. Насколько я могу судить, они функционально эквивалентны. Вы можете также потенциально написать это:

private static class ReverseComparator<T> implements Comparator<Comparable<T>>, Serializable { 

    // use serialVersionUID from JDK 1.2.2 for interoperability 
    private static final long serialVersionUID = 7207038068494060240L; 

    public int compare(Comparable<T> c1, Comparable<T> c2) { 
     return c2.compareTo((T) c1); 
    } 

    private Object readResolve() { 
     return reverseOrder(); 
    } 
} 

Моя только догадываться, почему они сделали это с помощью Comparable<Object> основано на том, что классы, которые реализуют Comparable (или Comparator) должны подчиняться equals() контракт, который делает использование Object. Таким образом, семантически это подчеркивает эту связь. Кроме этого, я не могу придумать, почему.

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