Java 16 でクラスのインターフェースのリストを収集するのに Stream#toList を使用できないのはなぜですか? 質問する

Java 16 でクラスのインターフェースのリストを収集するのに Stream#toList を使用できないのはなぜですか? 質問する

インターフェースを実装するクラスのオブジェクトをストリーミングしています。実装クラスではなく、インターフェースの要素のリストとして収集したいと思います。

これは、Java 16.0.1 のStream#toList方法では不可能と思われます。たとえば、以下のコードでは、最後のステートメントがコンパイルに失敗します。

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class WhyDodo {

    private interface Dodo { }

    private static class FancyDodo implements Dodo { }

    public static void main(String[] args) {
        final List<Dodo> dodos = Stream.of(new FancyDodo()).collect(Collectors.toList());
        final List<FancyDodo> fancyDodos = Stream.of(new FancyDodo()).toList();

        final List<Dodo> noFancyDodos = Stream.of(new FancyDodo()).toList();
    }
}

FancyDodoからの各要素を明示的に にキャストすることもできますDodo。ただし、簡潔にするために、 を使用することもできます.collect(Collectors.toList())

Java 16 で Stream#toList を使用してクラスのインターフェースのリストを収集できないのはなぜですか?

また、明示的にキャストするよりも良い解決策をお持ちの方がいらっしゃいましたら、ぜひ教えてください :)

ベストアンサー1

.collect(Collectors.toList())のシグネチャが次のとおりでcollectあるため機能します:

<R, A> R collect(Collector<? super T, A, R> collector);

重要なのは? super T

つまり、ストリームの型が であっても、toList()コレクターは として解釈できますCollector<Dodo,?,List<Dodo>( の結果.collect()を に割り当てる場合) 。List<Dodo>Stream<FancyDodo>

一方、の署名はStreamtoList()のようになります。

List<T> toList()

したがって、これを に対して実行すると がStream<FancyDodo>得られList<FancyDodo>、これを変数に割り当てることはできませんList<Dodo>

この場合は、stream.collect(Collectors.toList())の代わりにを使用することをお勧めします。stream.toList()

おすすめ記事