2017-10-22 38 views
9

Czytam kod źródłowy Java i znalazłem rzeczy jak poniżej:
http://www.java2s.com/Code/JavaAPI/java.util/newTreeSetEComparatorsuperEc.htm
Dlaczego konstruktor TreeSet <E> zaakceptować Super parametru E zamiast rozciągać E

I don” t zrozumieć, dlaczego parametr tego konstruktora to <? super E>.

Jako moje zrozumienie, powinno być <? extend E> zamiast <? super E>, ponieważ jeśli E jest porównywalne, dzieci E muszą być porównywalne, podczas gdy rodzice E mogą nie być.

Odpowiedz

14

Rozważmy trzy klasy: Drink, Juice extends Drink i OrangeJuice extends Juice.

Jeśli chcę TreeSet<Juice>, potrzebuję komparatora, który porówna dwa dowolne soki. Oczywiście zrobi to Comparator<Juice>.

Wykona to również Comparator<Drink>, ponieważ jest w stanie porównać dwa dowolne napoje, a więc dowolne dwa soki.

Nie zrobi tego Comparator<OrangeJuice>. Jeśli chcę dodać do mojego zestawu soków AppleJuice, to nie jest to zgodne z tym komparatorem, ponieważ może porównywać tylko soki pomarańczowe.

7

Tworzysz posortowany zestaw bananów. Aby to zrobić, musisz mieć możliwość porównania bananów. W ten sposób można użyć komparatora bananów. Ale jeśli masz komparator, który może sortować każdy rodzaj owoców (w tym banany), to też zadziała. Możesz więc użyć baneru Comparator<Fruit> lub nawet Comparator<Food>.

Dlatego użyto Comparator<? super E>.

Jeśli byłby to Comparator<? extends E>, byłbyś w stanie stworzyć zestaw bananów z Comparator<DriedBanana>. Ale to by nie zadziałało: komparator suszonych bananów może porównać tylko suszone banany. Nie wszystkie rodzaje bananów.

Więcej informacji można również czytać What is PECS (Producer Extends Consumer Super)?

4

powinno być zamiast bo jeśli E jest porównywalne, dzieci E muszą być porównywalne, podczas gdy rodzice E może nie być.

Comparator nie polega na obiektach Comparable.
Jest często używany jako alternatywa lub uzupełnienie.

W rzeczywistości, to konstruktor

public TreeSet(Comparator<? super E> comparator) {...} 

mogło:

public TreeSet(Comparator<E> comparator) {... } 

ale podając niższą ograniczony wieloznaczny, programiści JDK warunkiem większą elastyczność dla klas klienckich poprzez umożliwienie Comparator być współdziała zarówno z bieżącymi wystąpieniami klas, jak i instancjami klasy nadrzędnej. W niektórych przypadkach może to mieć sens.

Teraz:

public TreeSet(Comparator<? extend E> comparator) { 

nie może być ważny, ponieważ oznacza, że ​​można skończyć z compare() metody, która określa typ podklasy jako parametry.
Ale elementy z Set mogą zawierać wystąpienia określonej podklasy, ale nie tylko.

Wyobraźmy sobie ten kod:

TreeSet<CharSequence> set = new TreeSet<>(new Comparator<String>() { 

    @Override 
    public int compare(String o1, String o2) { 
     ... 
    } 
}); 

set.add("string"); 
set.add(new StringBuilder()); 
... 

Chcę porównać String s ale Set może zawierać String instancji, ale także wszelkie podklasa CharSequence takich jak StringBuilder, CharBuffer, itp ...
A jeśli był CharSequence nie abstract, może również zawierać ich wystąpienia.

W tym przykładzie rozumiemy, że koncepcyjnie Comparator<? extend E> jest nieprawidłowy.