Как получилось, что параметр типового типа "extends" Comparable не "реализует"?

Я попытался написать общую функцию, которая удаляет повторяющиеся элементы из массива.

public static <E extends Comparable<E>> ArrayList<E> removeDuplicate(E[] arr) {
    //do quicksort
    Arrays.sort(arr);
    ArrayList<E> list = new ArrayList<E>();
    int i;
    for(i=0; i<arr.length-1; i++) {
        if(arr[i].compareTo(arr[i+1]) != 0) { //if not duplicate, add to the list
            list.add(arr[i]);
        }
    }
    list.add(arr[i]); //add last element
    return list;
}

Как вы можете видеть, вы не можете передавать примитивный тип, например массив int [], поскольку я сравниваю элементы методом compareTo(), который определен в интерфейсе Comparable.

Я заметил первую строку (объявление метода):

public static <E extends Comparable<E>> ArrayList<E> removeDuplicate(E[] arr) {

Как получилось, что "extends Comparable"?

Сопоставимый интерфейс, поэтому почему он не "реализует Comparable"? Это первый раз, когда я написал универсальную функцию, поэтому я немного запутался в таких деталях. (любое удивление помешало бы мне понять..)

EDIT: эта статья относится к этой теме.

http://www.tutorialspoint.com/java/java_generics.htm

Ответ 1

Если вы хотите использовать то, что реализует, вы просто пишете как общий параметр

class Bar extends  Foo<String> { /* Code */}

Подстановочный знак, о котором Вы говорите, - это три

  1. "? extends Type": обозначает семейство подтипов типа Type. Это самый полезный шаблон
  2. "Супер Тип": обозначает семейство супертипов типа Тип
  3. "?": Обозначает набор всех типов или любой

Вы метод должен выглядеть так

public static <T extends Comparable<? super T>> Collection<T> sort(T[] list) {

        Collection<T> list = new ArrayList<T>();

         //do quicksort
        Arrays.sort(arr);

        Collection<T> list = new ArrayList<T>();
        int i;
        for(i=0; i<arr.length-1; i++) {
            if(arr[i].compareTo(arr[i+1]) != 0) { //if not duplicate, add to the list
                list.add(arr[i]);
            }
        }
        list.add(arr[i]); //add last element
//btw how do You know that last is not duplicate 
        return list;

}

Для подробностей, пожалуйста, посетите эту страницу

Ответ 2

Это просто соглашение, выбранное для дженериков. При использовании параметров ограниченного типа вы используете extends (даже если это может означать инструменты в некоторых случаях) или super.

Вы можете даже сделать что-то вроде <E extends Comparable<E> & Cloneable>, чтобы определить, что объект, который заменит параметр типа, должен реализовать оба этих интерфейса.

Ответ 3

С одной стороны, E может быть интерфейсом.