Ungewöhnliche Referenz mit generischen Typen bei Verwendung von JDK 1.8

9

Ich weiß, dass Varianten dieser Frage schon einmal gestellt wurden und ich dachte, dass ich das Java-8-Typ-Auflösungssystem verstehe, aber ich bekomme einen mehrdeutigen Referenzfehler für etwas, das ich nicht wirklich zweideutig finden sollte:

%Vor%

Die dritte Überladung erzeugt zwei kompilierte Fehler, wenn sie über JDK 1.8 kompiliert werden:

%Vor%

und

%Vor%

Nun, abgesehen von der Tatsache, dass der Rückgabetyp hier verwendet werden könnte, um die Mehrdeutigkeit aufzulösen und beide Fehler zu vermeiden, selbst wenn der Compiler das nicht tut, warum ist der Aufruf selbst mehrdeutig? Function<? super T, ? extends E> sollte nicht auf Function <? super T, E> castbar sein, da letzterer einen spezifischeren Typ hat, der keinen Platzhalter enthält. Zweitens, sollte es auch so sein, sollte der Compiler nicht die spezifischere Überladung wählen, die in diesem Fall das zweite Argument als List<T> anstelle von Collection<T> nehmen würde? Was fehlt mir hier?

Ich füge zur Verwirrung hinzu, das funktioniert, wenn ich den Aufruf in der dritten Überladung type angabe:

%Vor%

Die obigen Kompilierungen sind in Ordnung, auch wenn dieser Typ auf jeden Fall hätte abgeleitet werden müssen.

Das erste Beispiel, das unter JDK 1.7 gut kompiliert wurde, aber wenn ich JDK 1.8 verwende, auch wenn ich -source 1.7 angabe, verursacht es immer noch Fehler. Auch wenn es unter Java 8 mehrdeutig ist, sollte der Compiler trotzdem funktionieren, wenn er auf Sprachlevel 7 eingestellt ist, richtig?

Was mache ich falsch?

    
Joel Croteau 04.04.2016, 21:34
quelle

1 Antwort

0

Ich hob dies von einem Kommentar auf, weil ich es etwas besser erklären wollte.

Ich bin mir ziemlich sicher, dass dies wie bei diesem nicht-generischen Beispiel funktioniert:

%Vor%

Das heißt, Function<? super T, E> ist aus irgendeinem Grund spezifischer als Function<? super T, ? extends E> .

Eine Erklärung dafür ist, dass Function<? super T, E> als Untertyp von Function<? super T, ? extends E> betrachtet werden kann. Dies ist normalerweise richtig, zum Beispiel List<String> ist ein Subtyp von List<? extends String> , aber ich bin nicht vertraut genug mit der Typinferenz, um sicher zu sagen, dass dies genau so ist, wie das Beispiel funktioniert.

Eine andere Möglichkeit, es intuitiv zu erklären, wäre, dass die Nicht-Wildcard E immer genau mit ihrem Argument übereinstimmt, so dass es immer spezifischer sein kann.

Keiner von beiden ist wirklich gut genug für mich, vor allem, weil Sie sagen, dass dies für Sie unter 1.7 kompiliert wurde und die Subtypisierung mit Platzhaltern dann existierte. Es kommt wirklich darauf an, wie sich die Typinferenz geändert hat.

Ich denke, die wahre Antwort wird daher von angegeben 18.5.4 , was ich gerade nicht gut genug verstehe, um es sicher zu sagen. (Auch normalerweise viel zu dicht um daraus zu zitieren ...)

  

Function<? super T, ? extends E> sollte nicht in Function <? super T, E> umgewandelt werden können, da letzterer einen spezifischeren Typ hat, der keinen Platzhalter enthält.

Dies ist die richtige Intuition für eine Zuweisung, aber wenn Sie fn an die generische Methode übergeben, werden die Platzhalter erfasst. Siehe z.B. Ссылка .

Der Mehrdeutigkeitsfehler ist ein wenig verblüffend, aber abgesehen vom Rückgabetyp sind beide Methoden anwendbar.

    
Radiodef 05.04.2016 00:35
quelle

Tags und Links