2
import org.junit.Test;

import java.util.stream.IntStream;

public class GomanTest {

    @Test
    public void someTest() {
        IntStream.of(2, 3, 1).collect(Container::new, Container::add, null);
    }
}


class Container<T> {

    void add(T t) {
        System.out.println("this is container " + t);
    }
}

出力:

this is container 2
this is container 3
this is container 1

これは 1.8.0_45.jdk で正常に実行されます。Container#add はどのように ObjIntConsumer#accept に変換されますか?

4

1 に答える 1

6

メソッドContainer.addは、インスタンスを呼び出す必要があるインスタンス メソッドです。フォーム上のメソッド参照ClassName::methodNameはインスタンスにバインドされていないため、Container::addの機能シグネチャは(Container<T>,T)です。

型引数Containerもターゲット型も指定しなかったため、コンパイラは を推論しContainer<Object>ます。ここでContainer::add推測されたシグネチャも同様です。これは、シグネチャを持つ のメソッドに(Container<Object>,Object)適しています。acceptObjIntConsumer<Container<Object>>(Container<Object>,int)

2 番目の引数は、type の値を受け入れることができます。intIntegerObject

結果を変数に代入する場合も同様に機能し、ターゲット タイプを提供しContainer<Object>ますContainer<Integer>

Container<Integer> collected
   = IntStream.of(2, 3, 1).collect(Container::new, Container::add, null);

または などIntegerを消費できる型引数も同様に機能します。SerializableNumber


インスタンス メソッドへの無制限参照の詳細については、「Java 8 における「特定の型の任意のオブジェクト」の意味」</a> を参照してください。


補足として、ストリームのメソッドは引数collectを受け入れることは想定されておらず、実装は受け入れていません。プリミティブ ストリームで動作するパスは、現在の実装の不具合であり、パスするコードは次のバージョンで壊れる可能性があります。Tagir nullStreamnullnullValeev が指摘したように、Java 9 の現在の開発段階では、動作は既に変更されています。

于 2015-09-15T10:57:01.077 に答える