2013-03-12 17 views
19

Ich habe Kurse in fortgeschrittener Programmierung an meiner Universität und ich habe ein wenig Probleme zu verstehen, wie dieser Code funktioniert.Fortgeschrittener Polymorphismus in Java

public final class GenericClass<T> { 
    private void overloadedMethod(Collection<?> o) { 
     System.out.println("Collection<?>"); 
    } 

    private void overloadedMethod(List<Number> o) { 
     System.out.println("List<Number>"); 
    } 

    private void overloadedMethod(ArrayList<Integer> o) { 
     System.out.println("ArrayList<Integer>"); 
    } 

    public void method(List<T> l) { 
     overloadedMethod(l); 
    } 

    public static void main(String[] args) { 
     GenericClass<Integer> test = new GenericClass<Integer>(); 
     test.method(new ArrayList<Integer>()); 
    } 
} 

Warum funktioniert dieser Code drucken "Collection <? >"?

Antwort

14

Die Deklaration method(List<T> l) gibt keine Grenzen für den Typ T an. Es gibt keine Garantie, dass T die Nummer oder eine Unterklasse von Number ist. Daher kann der Compiler nur entscheiden, dass diese Methode overloadedMethod(Collection<?> o) aufruft.

Hinweis: Nach der Kompilierung sind die Informationen zu Generika in den Klassendateien nicht mehr verfügbar.

+0

dank ist, Ihre Antwort erklärt auch, warum nach dem Wechsel 'overloadedMethod (List o)' auf 'overloadedMethod (List o)' Programm druckt 'Liste ' statt 'Sammlung ' –

+0

die Das Wichtigste ist dein letzter Satz. Das erklärt alles! –

+0

Ziemlich gute Antwort, aber -1, um Ihre Aufmerksamkeit auf die Tatsache zu lenken, dass die Deklaration von 'GenericClass ' stattdessen zum selben Aufruf von 'overloadedMethod (Collection ) führt'. Da ist also noch etwas anderes los. –

-1

Jedes Mal, wenn Sie einen generischen Typ zu definieren, eine entsprechende Roh-Typ wird automatisch bereitgestellt Diese Methode

public void method(List<T> l) { 

} 

mit

public void method(List<Object> l) { 

} 

ersetzt Wenn Sie über Wildcard-Typen lesen, werden Sie sehen, dass List<Number> und List<Object> oder ArrayList<Integer> und List<Object> hat keine Art Beziehung. List<Object> ist ein Subtyp des Collecion<?> daher wird diese Methode aufgerufen.

+0

Tatsächlich reicht die Argumentation hier nicht aus, um die Frage zu beantworten. Der Compiler entscheidet, welche Methodenüberladung aufgerufen werden soll, was * vor * type löscht. –

-1

, wenn Sie mit der Methode behandeln Überlastung Sie drei Konzepte im Kopf setzen müssen:

  1. Widening
  2. Boxen
  3. Var_args

Ihr Problem in dem ersten Punkt liegt, die wird immer größer Der Java-Compiler gibt jedem dieser Konzepte die gleiche Priorität wie oben aufgeführt. Daher bevorzugt er die Erweiterung und wenn Sie Ihre Methode als test.method(new ArrayList<Integer>()); aufrufen der Compiler findet, dass ArrayList<Integer>()-Collection<?> erweitert werden konnte und da es die höchste Priorität hat es nennt diese Version und vernachlässigt die anderen Hinweis: Wenn Sie die Deklaration der beiden anderen Methoden zu private void overloadedMethod(ArrayList<?> o) und private void overloadedMethod(List<?> o) der Compiler auch die Collection<?> nennen ändern Version, weil es den bevorzugten

+0

Nr. Wenn private void überladen Methode (Liste o) {// dann Liste Methode wird über Collection aufgerufen werden. – AmitG

+0

hast du es probiert ?? –

+0

"@Java Player: Ich besuche dieses Forum auch im Büro und aktualisiere mich so schnell wie möglich. BTW hast du es versucht? Wenn du es dann versucht hast, dann lass die Schlussfolgerung hier fallen. – AmitG