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.
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?
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:
Aber da es in einem rohen Stream
aufgerufen wird, ist es so, als wäre die Deklaration
Das Ergebnis des Aufrufs von map()
ist einfach ein Stream
. Die Signatur von collect()
ist mit Generics gefüllt:
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%