2013-08-23 14 views
9

Chociaż starałem się rozwiązać ćwiczenia from generics tutorial Q&A Moje odpowiedzi były nieco odmienneJak napisać ogólną metodę znajdowania maksymalnego elementu i wywoływania tej metody?

moje odpowiedzi

public static <T extends Comparable<? super T>> 
    T max(List<? extends T> list, int begin, int end) //Option1 

public static <T extends Comparable<T>> 
    T max(List<? extends T> list, int begin, int end) //Option2 

z cytowanej odpowiedzi poniżej

Więc moje pytanie brzmi

  • Opcja 1 : Czy to by miało jakikolwiek wpływ, gdyby T extends Object & Comparable<? super T> zostaje zastąpione przez T extends Comparable<? super T>. Czy nie jest to domniemana extends Object?

  • Opcja 2: Czy zmieniłoby się, gdyby Comparable<? super T> zastąpiono Comparable<T>? Jeśli tak to jak ?

  • Uzupełnianie kodu Eclipse tworzy lokalną zmienną List<? extends Comparable<? super Comparable<? super T>>> list; na Ctrl + 1 max(list, 1, 10);, która jest nieco dłuższa. Jak zdefiniować klasy (hierarchię), która rozszerza się o Comparable<? super T>, tworzy listę i dodaje instancje do listy i wywołuje poniższą metodę? Zasadniczo chcę wiedzieć, jak wywołać max() po dodaniu instancji klasy A or B do listy gdzie class B extends A


napisać metodę rodzajową znaleźć element maksymalny w zakresie [początek, koniec) lista.

Odpowiedź:

import java.util.*; 

public final class Algorithm { 
    public static <T extends Object & Comparable<? super T>> 
     T max(List<? extends T> list, int begin, int end) { 

     T maxElem = list.get(begin); 

     for (++begin; begin < end; ++begin) 
      if (maxElem.compareTo(list.get(begin)) < 0) 
       maxElem = list.get(begin); 
     return maxElem; 
    } 
} 
+2

Częściowa odpowiedź tutaj: http://stackoverflow.com/questions/10339338/t-extends-object-e-vs-t-extends-e –

+0

Naprawdę nie rozumiem twojego trzeciego pytania. Czy możesz trochę to rozwinąć? –

+0

Dla jakiego wywołania metody zaćmienie należy utworzyć tę zmienną lokalną? Nie rozumiem, dlaczego miałby to zrobić. Przynajmniej zagnieżdżony Porównywalny rodzajowy typ nie jest tutaj naprawdę rozsądny. –

Odpowiedz

8

Czy to żadnej różnicy, jeśli Comparable<? super T> otrzymuje z Comparable<T>? Jeśli tak to jak ?

Pamiętaj, że porównawczych zawsze są konsumenci, tj Comparable<T> zużywa T instancje, tak powinno być zawsze preferuje użycie Comparable<? super T> zamiast Comparable<T> (podając - PECS). Byłoby to różnicą w przypadku porównywania typu, którego super klasa implementuje Comparable<SuperType>. Rozważmy następujący kod:

class Parent implements Comparable<Parent> { 
    protected String name; 

    @Override 
    public int compareTo(Parent o) { 
     return this.name.compareTo(o.name); 
    } 
} 

class Child extends Parent { 
    public Child(String name) { 
     this.name = name; 
    } 
} 

Teraz, jeśli dać parametr typu jak T extends Comparable<T>, nie będzie w stanie wywołać tę metodę za List<Child>, jak Dziecko nie implementuje Comparable<Child> ale Comparable<Parent>:

public static <T extends Comparable<T>> T max(List<? extends T> list, int begin, int end) { 
    ... 
} 

public static void main(String[] args) { 
    List<Child> list = new ArrayList<Child>(); 
    max(list, 0, 2); // Error with current method. Child does not implement Comparable<Child> 
} 

W związku z tym granice parametrów powinny wynosić T extends Comparable<? super T>.

pamiętać, że nie można zmienić swoją Dziecko klasę do:

class Child extends Parent implements Comparable<Child> 

ponieważ w takim przypadku Dziecko klasa będzie rozciągać się od innej instancji tego samego typu rodzajowego, co jest niedozwolone.


Czy to żadnej różnicy, jeśli T extends Object & Comparable<? super T> otrzymuje z T extends Comparable<? super T>. Czy nie rozszerza Object niejawnie?

Cóż, istnieje różnica między tymi dwoma granicami. W powiązaniu z usunięciem parametru type wynosi , natomiast usunięcie jest następujące: .

Więc bez Object związany Twój kod zostanie skompilowany do:

public static Comparable max(List list, int begin, int end) 

Problem może przyjść, kiedy jesteś generifying spuścizny kod nierodzajową. Konieczne jest podanie wartości Object jako górnej granicy, aby uniknąć złamania zgodności z kodami bajtowymi. Więcej informacji na ten temat można znaleźć pod tym linkiem: Angelika Langer - Programming Idioms

+0

Wymazanie metody powoduje tylko różnicę dla typów parametrów wejściowych, a nie typu zwracanego, a granica obiektu "Object" nie ma tu znaczenia: nadal jest to wartość 'max (List, int, int) '. "Obiekt" jest tutaj naprawdę niepotrzebny. –

+0

@LouisWasserman. Cóż, na pierwszy rzut oka też pomyślałem to samo, potem przeczytałem link, który dodałem na końcu. Mówi, że jest to konieczne do utrzymania zgodności kodu bajtowego. –

+0

@RohitJain W rzeczywistości 'max (lista, 0, 2);' skompiluje się dobrze. ale 'Child child = max (lista, 0, 2);' nie skompiluje się. – Kachna

0

Wygląda na to, że jest więcej symboli wieloznacznych niż jest to konieczne. Pewnie iść z

public static <T extends Comparable<? super T>> 
    T max(List<T> list, int begin, int end) 

w jeszcze bardziej ograniczone wersji:

public static <T extends C, C extends Comparable<C>> 
    T max(List<T> list, int begin, int end) 

tj T musi mieć super typ, który jest porównywalny do sama. Na przykład T nie może być Foo

class Foo implements Comparable<Object> 

Foo nie ma sensu i tak; Porównywalny może być jedynie sensownie porównany z jego rodzajem. Klauzula C extends Comparable<C> potwierdza ten fakt.

Powiązane problemy