2014-05-21 2 views
12

Betrachten Sie das folgende CodefragmentWarum ist `Stream.collect` typsicher und` Stream.toArray (IntFunction <A[]>) `nicht?

String strings[] = {"test"}; 
final List<String> collect = java.util.Arrays.stream(strings).collect(java.util.stream.Collectors.toList()); 
final Double[] array = java.util.Arrays.stream(strings).toArray(Double[]::new); 

Warum kann Java die richtige Art in der Collect-Fall (Änderung der generischen Art von collect auf zB Doppel führt zu einem Fehler der Kompilierung) garantieren, aber nicht in dem Array Fall (kompiliert gut, trotz apply(int) von Double[]::new gibt Double[], nicht Object[], aber löst ArrayStoreException, wenn falsch wie oben verwendet)?

Was wäre der beste Weg, einen Kompilierzeitfehler zu generieren, wenn ich den Typ des Streams ändere, ohne die angegebene IntFunction im toArray-Aufruf zu ändern?

Antwort

9

Die Signatur der Methode Stream::toArray sieht wie folgt aus. Bitte beachten Sie, dass die Typparameter T und A völlig unabhängig sind.

public interface Stream<T> { 
    <A> A[] toArray(IntFunction<A[]> generator); 
} 

In der Quelle der ReferencePipeline.java, können Sie den folgenden Kommentar finden:

Da A keine Beziehung zu U (nicht möglich zu erklären, dass A eine obere Schranke ist von U) wird es keine statische Typprüfung sein. Verwenden Sie daher einen unformatierten Typ und nehmen Sie an anstatt die Trennung von A und U in der gesamten Codebasis zu propagieren. Der Laufzeittyp von U wird nie auf Gleichheit mit dem Komponententyp des Laufzeittyps A[] geprüft. Die Laufzeitprüfung wird ausgeführt, wenn ein Element in A[] gespeichert ist. Wenn also A kein Super-Typ U ist, wird ein ArrayStoreException geworfen.

+0

Ist dies einer der Fälle, in denen 'A super T' helfen würde? Wenn dem so ist, dann ist es ziemlich interessant, dass sie es nicht dafür festgelegt haben, denn es scheint mir ein "Muss" zu sein, wenn es in einer solchen API ist. – skiwi

+0

Nun, ich bin auf der Suche nach dem Grund, dass sie völlig unabhängig sind, wie Sie darauf hingewiesen haben. Einen '' zu setzen scheint leicht genug zu sein. Daher würde ich ein Problem in den Implementierungen der Stream-Schnittstelle oder etwas Ähnliches erwarten. – muued

+6

@mued Bitte beachten Sie, dass '' syntaktisch * in Typdeklarationen nicht möglich ist. Du kannst nur '' haben? Super T 'als ein Typ, aber Sie können das'? 'nicht erfassen. Dies ist im Gegensatz zu 'X extends T', die '? verlängert T'. Es wurde zu der Zeit, als Generika erstellt wurden, aus Java weggelassen, weil es als * nicht nützlich genug * eingestuft wurde. – skiwi

Verwandte Themen