2016-01-24 6 views
7

編集:ここに私の質問に答えました。要約すると、私は非静的メソッド参照の使い方について混乱していました。関数インタフェースと参照されるメソッドには、異なる数のパラメータがあります。二重コロンの使用 - 静的メソッド参照と非静的メソッド参照の違い

私の質問には、commentと回答が受け入れられました。


現在、Stream reductionメソッド(https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html)に関するJavaチュートリアルを読んでいます。そこで私は間違っていると思ったコードを見つけたので、より簡単なコードを作りました。 Stream.collecthttps://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#collect-java.util.function.Supplier-java.util.function.BiConsumer-java.util.function.BiConsumer-)用のJavaドキュメントで

Averager averageCollect = zahlen.stream() 
    .collect(Averager::new, Averager::addcount, Averager::combine); 

それが二番目のパラメータとしての機能が一致していることを述べている:

// B.java file 
import java.util.*; 

public class B 
{ 
    public static void main(String[] args) 
    { 
    List<Integer> zahlen = new LinkedList<Integer>(); 
    zahlen.add(1); 
    zahlen.add(2); 
    zahlen.add(3); 
    Averager averageCollect = zahlen.stream() 
     .collect(Averager::new, Averager::addcount, Averager::combine); 
    System.out.println(averageCollect.average()); 
    } 
} 

// Averager.java from the official Java tutorial 
public class Averager 
{ 
    private int total = 0; 
    private int count = 0; 

    public double average() { 
     return count > 0 ? ((double) total)/count : 0; 
    } 

    public void addcount(int i) { total += i; count++;} 
    public void combine(Averager other) { 
     total += other.total; 
     count += other.count; 
    } 
} 

私は、これは動作しないだろうと思った理由は、ラインであります2つの引数を持つ抽象メソッドを持つ関数インタフェースBiConsumerが必要です。しかし、Averager.addcountAverager.combineには1つのパラメータしかありません。

私はまた、ラムダ式でチェック:

Averager averageCollect = zahlen.stream() 
    .collect(Averager::new, (a,b) -> a.addcount(b), (a,b) -> a.combine(b)); 

また、このコードは動作します第2および第3のパラメータとして、私は、2つのパラメータを持つ関数を持っています。

パラメータが1つのみの関数が指定されていても、上記のコードが正確に動作するのはなぜですか。そして、私はAverager.addcountAverager.combineの両方にこのような2つのパラメータを持つように変更すると、なぜエラーメッセージが表示されますか?私は、次のエラーメッセージを取得することを行う場合

public void addcount(Averager one, Integer i) 
public void combine(Averager one, Averager other) 

B.java:12: error: no suitable method found for collect(Averager::new,Averager::addcount,Averager::combine) 
     .collect(Averager::new, Averager::addcount, Averager::combine); 
    ^
    method Stream.collect(Supplier,BiConsumer,BiConsumer) is not applicable 
     (cannot infer type-variable(s) R#1 
     (argument mismatch; invalid method reference 
      cannot find symbol 
      symbol: method addcount(R#1,Integer) 
      location: class Averager)) 
    method Stream.collect(Collector) is not applicable 
     (cannot infer type-variable(s) R#2,A 
     (actual and formal argument lists differ in length)) 
    where R#1,T,R#2,A are type-variables: 
    R#1 extends Object declared in method collect(Supplier,BiConsumer,BiConsumer) 
    T extends Object declared in interface Stream 
    R#2 extends Object declared in method collect(Collector) 
    A extends Object declared in method collect(Collector) 
1 error

私は理解して助けてください。

+3

_current item_が最初のパラメータになります。したがって、「BiConsumer」は、 'static(静的)メソッドの場合はメソッド(a、b)、インスタンスメソッドの場合はa.method(b)'となります。あなたの壊れた例では、 **インスタンス**メソッドを渡しました。 –

+2

参照「Oracleのチュートリアル「メソッド参照」」(http://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html#PageTitle)メソッド参照の種類」を参照してください。 – Holger

答えて

6
Averager averageCollect = zahlen.stream() 
    .collect(Averager::new, Averager::addcount, Averager::combine); 

これは問題ありません。すべての非静的メソッドが隠されthisパラメータを持って覚えてい

Averager averageCollect = zahlen.stream() 
    .collect(() -> new Averager(), 
      (myAverager, n) -> myAverager.addcount(n), 
      (dst, src) -> dst.combine(src)) 

に相当します。この場合、これをaccumulatorcombinerコールバックの最初の引数に(正しく)バインドしています。

それはまたのような静的メソッドで動作します。うまくいけば何が起こっているのか、それが明確になり

public static void addcount(Averager a, int i) { 
    a.total += i; 
    a.count++; 
} 
public static void combine(Averager dst, Averager src) { 
    dst.total += src.total; 
    dst.count += src.count; 
} 

しかし、コードを変更する必要はありません。

関連する問題