Warum bewertet diese Java 8-Stream-Operation Object anstelle von ListObject oder nur List?

8

Ich arbeite mit einer 3D-Party-Bibliothek, und sie geben Collections zurück, denen Typspezifikationen fehlen (z. B. public List getFoo(); ), und ich versuche, ihre Rückgabetypen zu konvertieren und eine Liste mit einem richtigen Typ zurückzugeben.

Ich habe ein einfaches Beispiel erstellt, das das Problem veranschaulicht. z.B.

edit Die ursprüngliche Frage deklariert l2 als ArrayList anstatt als List , das ist jetzt korrigiert.

%Vor%

Dies kann nicht kompiliert werden.

%Vor%

Wenn ich das Programm leicht modifiziere, so kompiliert es und ich kann den Rückgabetyp der Stream / Collect-Operation überprüfen. Es "funktioniert", obwohl ich das Ergebnis abgeben müsste.

z.B.

%Vor%

Running this zeigt ...

%Vor%

Wie erwartet.

Also macht Collectors.listCollector () zur Laufzeit das Richtige, aber wird dieses Kompilierzeitverhalten erwartet? Wenn ja, gibt es einen "richtigen" Weg darum?

    
Bill 13.05.2016, 16:09
quelle

2 Antworten

12

Die stream() , map() , collect() und alle anderen Stream-Methoden beruhen auf generischer Typisierung, damit die Dinge gut funktionieren. Wenn Sie einen Rohtyp als Eingabe verwenden, werden alle Generika gelöscht und alles wird zu einem Rohtyp. Wenn Sie beispielsweise List<String> haben, erhalten Sie durch Aufrufen der Methode stream() ein Objekt vom Typ Stream<String> .

Wenn Sie jedoch mit einem Rohtyp List beginnen, erhalten Sie durch Aufruf von stream() stattdessen ein Objekt vom Rohtyp Stream .

Die Methode map() hat diese Deklaration:

%Vor%

Aber da es in einem rohen Stream aufgerufen wird, ist es so, als wäre die Deklaration

%Vor%

Das Ergebnis des Aufrufs von map() ist einfach ein Stream . Die Signatur von collect() ist mit Generics gefüllt:

%Vor%

Wenn es mit einem unformatierten Typ aufgerufen wird, wird es nach

gelöscht %Vor%

Der Rückgabetyp Ihrer Stream-Pipeline ist Object , wenn die Quelle ein unformatierter Typ ist. Offensichtlich ist dies nicht kompatibel mit ArrayList<String> und Sie erhalten einen Kompilierungsfehler.

Um dies zu beheben, bringen Sie Ihre Typen so schnell wie möglich in die generische Welt. Dies wird wahrscheinlich zu ungeprüften Umwandlungen führen, und Sie sollten die Warnung wahrscheinlich unterdrücken. Natürlich nur, wenn Sie sicher sind, dass die zurückgegebene Sammlung nur Objekte des erwarteten Typs enthält.

Außerdem, wie Hank D gezeigt hat, gibt der Kollektor toList() eine List zurück, nicht% Code%. Sie können den Rückgabewert entweder einer Variablen vom Typ ArrayList zuweisen oder Sie können List verwenden, um explizit eine Instanz von toCollection() zu erstellen.

Hier ist der Code mit diesen Änderungen enthalten:

%Vor%     
Stuart Marks 14.05.2016, 01:37
quelle
3

Collectors.toList () gibt eine List und keine ArrayList zurück. Dies wird kompilieren:

%Vor%     
Hank D 13.05.2016 16:36
quelle

Tags und Links