Warum die generische Version des Collection-Parameters einen Aufruf erhält

8

Hier ist ein Code-Segment

%Vor%

Ich erwarte, dass es eine überladene Methode mit Arraylist-Parameter aufrufen würde, aber Collection wird warum genannt?

    
test 23.08.2015, 04:42
quelle

2 Antworten

5

Dieser genaue Code wird in einem Beispiel in Angelika Langers Webseite zu Java-Generika

Ich werde die Erklärung posten, falls die Seite jemals untergeht:

  

Das Programm druckt:

     

overloadedMethod (Sammlung)

     

Man hätte erwarten können, dass Version für ArrayList aufgerufen wird, aber das ist wiederum die falsche Erwartung. Lassen Sie uns sehen, worauf der Compiler die generische Klasse umsetzt.

     

Beispiel (nach dem Typ löschen):

%Vor%
  

Man könnte fälschlicherweise glauben, dass der Compiler entscheiden würde, dass die Listenversion der überladenen Methode die beste Übereinstimmung ist. Aber das wäre natürlich falsch. Die Listenversion der überladenen Methode war ursprünglich eine Version, die eine Liste als Argument verwendet, aber beim Aufruf wird eine Liste übergeben, wobei T ein beliebiger Typ sein kann und keine Zahl sein muss. Da T ein beliebiger Typ sein kann, ist die einzige durchführbare Version der überladenen Methode die Version für Collection.

Wenn Sie die Collection-Methode auskommentieren, erhalten Sie einen Compiler-Fehler, weil die List- und ArrayList zu spezifisch für alle möglichen <T> -Typen sind.

    
dkatzel 23.08.2015 05:07
quelle
4

Sehen Sie sich Abschnitt 15.12 im Java-Dokument mit dem Titel "Method Invocation Expressions" an ". Genauer gesagt Abschnitt 15.12.2.5 Auswählen der spezifischsten Methode :

  

Wenn mehrere Methoden gleichzeitig verfügbar und auf eine Methode anwendbar sind   Aufruf, ist es notwendig, einen zu wählen, um den Deskriptor für die Laufzeit bereitzustellen   Methodenversand Die Java-Programmiersprache verwendet die Regel, die am meisten   spezifische Methode wird gewählt.

     

Die informelle Intuition ist, dass eine Methode spezifischer ist als   ein anderer, wenn irgendein Aufruf, der von der ersten Methode behandelt wurde, übergeben werden könnte   auf die andere ohne einen Kompilierzeitfehler. In Fällen wie einem   explizit eingegebenes Lambda-Ausdruckargument (§15.27.1) oder eine Variable   Arity-Aufruf (§15.12.2.4), etwas Flexibilität ist erlaubt anzupassen   eine Unterschrift für die andere.

Darüber hinaus heißt es in Abschnitt 8.4.9 Überladung :

  

Wenn eine Methode aufgerufen wird (§15.12), die Anzahl der tatsächlichen Argumente (und alle   explizite Typargumente) und die Kompilierungszeittypen der Argumente verwendet werden,   zur Kompilierzeit, um die Signatur der Methode zu ermitteln, die aufgerufen wird   (§15.12.2). Wenn die Methode, die aufgerufen werden soll, eine Instanzmethode ist, die tatsächliche   Die Methode, die aufgerufen werden soll, wird zur Laufzeit unter Verwendung der dynamischen Methodensuche ermittelt   (§15.12.4).

Unter Berücksichtigung dieser beiden Abschnitte können wir feststellen, dass, da method ein List<T> -Objekt übergeben wird, das spezifischste Java-Ziel das eines Platzhalters Collections ist.

Beachten Sie, dass Sie das Argument selbst dann in ArrayList<T> geändert haben:

%Vor%

Dieselbe Methode wird immer noch aufgerufen, da die spezifische Überladung, die ArrayList akzeptiert, zu spezifisch ist - ArrayList<Integer> vs. Ihr Argument ist ArrayList<T> und Java bestimmt Collection<?> als beste Übereinstimmung (Sie können von Natürlich umgehen Sie es, indem Sie entweder den Parametertyp von method ändern oder den Parameter overloadedMethod spezifischer machen.

    
Ori Lentz 23.08.2015 05:11
quelle

Tags und Links