Mehrdeutige überladene generische Methode mit Platzhalter in Parameter

8

Angesichts der folgenden Erklärungen

%Vor%

Warum bekomme ich einen Kompilierfehler für den folgenden Code:

%Vor%

BTW, das Problem kann behoben werden, indem die Deklaration der zweiten Methode in

geändert wird %Vor%     
Cephalopod 23.03.2015, 13:39
quelle

1 Antwort

3

Zunächst eine sehr interessante Frage.

Ohne Generika

Betrachten Sie den folgenden Code:

%Vor%

Wir haben immer gelernt, dass der Compiler die spezifischste Methode wählt. Und tatsächlich wird der oben erwähnte Code, vorausgesetzt, Sie rufen foo((NoGenericsSuperSpecial) null) an, folgendes ausdrucken:

  

Sonderlieferung

So weit, so gut.

Generika

Lassen Sie uns nun ein paar generische Verhaltensweisen testen:

%Vor%

Dieser Code wird kompiliert. Der Compiler findet zwei Übereinstimmungen - sowohl Base<? extends Number> als Special<? extends Number> apply -, aber der Compiler ist in der Lage herauszufinden, welche die spezifischste ist: er wählt void foo(Special<? extends Number>) , weil beide Captures der ungebundenen Wildcards gleich sind.

Aber lassen Sie uns foo(Base<...>) method neu schreiben und lassen Sie die restlichen unberührt:

%Vor%

Jetzt tritt der folgende Fehler auf:

  

Verweis auf foo ist mehrdeutig   Sowohl die Methode foo(Base<? extends Integer>) als auch die Methode foo(Special<? extends Number>) stimmen mit

überein

Bevor der genaueste Typabgleich ermittelt wird, behandelt der Compiler Typvariablen. Anscheinend kann der Compiler nicht herausfinden, ob <? extends Number> oder <? extends Integer> gilt, der Typ der Variablen selbst wurde ignoriert ( Base oder Special ).

Es scheint, dass die Handhabung des Variablentyps vor die Auswahl der Methodensignaturen bezüglich der Vererbung ist.

Eins (oder zumindest ich selbst) sollte erwarten, dass der Compiler foo(Special<? extends Number>) auswählt, aber das ist nicht der Fall.

Der Grund

Ich weiß nicht, ob der Compiler nicht in der Lage ist, den spezifischsten bezüglich Generika auszuwählen, oder er ist nicht dafür konfiguriert.

Siehe die Java-Sprachspezifikation § 18.5 oder § 4.5.1 für weitere Details .

Lass mich etwas Zeit nehmen, um mehr von Generika zu lesen, also können wir es vielleicht herausfinden ...

    
MC Emperor 24.03.2015 00:41
quelle