Generik-Typ-Inferenz schlägt fehl?

8

Beispiel A

Studieren Sie das folgende Snippet:

%Vor%

Kann jemand erklären, warum Typinferenz für die Zuweisung zur lokalen Variablen p funktioniert, aber nicht für den zweiten tatsächlichen Parameter zu process ?

Beispiel B

Das ist vielleicht einfacher zu verstehen:

%Vor%

Gleiche Frage: Warum kompiliert es nicht?

Ich hoffe, dass Collections.emptySet() nur für ANY parametrisierter Set type funktionieren würde.

    
polygenelubricants 10.11.2010, 22:41
quelle

2 Antworten

8

Ihr zweiter Aufruf von anyPair() hat keine Möglichkeit, seine Typen zu bestimmen, und daher wird standardmäßig <Object, Object> verwendet.

Der Compiler bricht process(p, anyPair()); in seine Teile und bearbeitet sie einzeln. Wenn es das tut, muss es zuerst die Argumente verarbeiten, um ihre Typen zu bestimmen, die dann bei der Verarbeitung von process verwendet werden können.

Wenn es zum Prozess anyPair() geht, gibt es keine Typinformationen für dieses Stück, weil es nicht weiß, dass es zu diesem Zeitpunkt Teil von process ist. Der Standardwert ist <Object, Object> , was zu einem Typenkonflikt führt, wenn Sie process betrachten.

Das gleiche passiert mit Ihrem zweiten Beispiel. Collections.emptySet() muss von selbst verarbeitet werden, hat aber keine Möglichkeit, die benötigten Typen zu bestimmen.

Es gibt zwei Möglichkeiten, dies zu lösen:

Als Erstes geben Sie dem Compiler die Informationen, die er für die Typinferenz benötigt, genauso wie beim ersten Aufruf von anyPair() , indem Sie ihn in einer temporären Variablen mit dem richtigen Typ speichern.

Der zweite (dank @BalusC) ist ExampleA.<String, Integer>anyPair() zu verwenden. Diese Syntax legt explizit die erforderlichen Typen fest, ohne über den Aufruf hinaus schauen zu müssen.

    
Alan Geleynse 10.11.2010, 22:49
quelle
0

Warum:

Collections.emptySet() versucht den zurückzugebenden Typ abzuleiten. Es ist nicht möglich, weil E Object oder String sein könnte. Beide sind gültige Übereinstimmungen für den Prozess. Generische Parameter sind standardmäßig unveränderlich, nicht kontravariant. Das bedeutet, dass Integer extends Number aber List<Integer> nicht List<Number> erweitert. Bei wird jedoch List<? extends Number> erweitert.

Lösungen:

Verwenden Sie eine Zuweisung, um den Typ abzuleiten:

%Vor%

Schreiben Sie explizit den Typ:

%Vor%

Erlaube explizite Kontravarianz (dies ist jedoch wahrscheinlich nicht das, was du willst):

%Vor%     
Eyal 10.12.2013 10:35
quelle

Tags und Links