Java 双冒号的使用-静态和非静态方法引用之间的差异

Java 双冒号的使用-静态和非静态方法引用之间的差异,java,lambda,callback,java-8,java-stream,Java,Lambda,Callback,Java 8,Java Stream,编辑:我的问题已经回答了。总而言之,我对非静态方法引用的用法感到困惑。在这里,功能接口和引用方法具有不同数量的参数 回答我问题的是答案和公认的答案 我目前正在阅读关于流缩减方法()的Java教程。在那里我发现了一段我认为是错误的代码,所以我制作了一个更简单的代码来确保 // B.java file import java.util.*; public class B { public static void main(String[] args) { List<Int

编辑:我的问题已经回答了。总而言之,我对非静态方法引用的用法感到困惑。在这里,功能接口和引用方法具有不同数量的参数

回答我问题的是答案和公认的答案


我目前正在阅读关于流缩减方法()的Java教程。在那里我发现了一段我认为是错误的代码,所以我制作了一个更简单的代码来确保

// 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;
    }
}
Stream.collect
()的Java文档中,它指出作为第二个参数,需要一个与函数接口
BiConsumer
匹配的函数,该函数具有一个带有两个参数的抽象方法。但是
Averager.addcount
Averager.combine
只有一个参数

我还检查了lambda表达式:

Averager averageCollect = zahlen.stream()
  .collect(Averager::new, (a,b) -> a.addcount(b), (a,b) -> a.combine(b));
这段代码也可以工作,作为第二个和第三个参数,我有两个参数的函数

尽管只给出了一个参数的函数,但我上面写的代码究竟是如何工作的?当我同时更改
Averager.addcount
Averager.combined
以获得如下两个参数时,为什么会出现错误消息

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 B.java:12:错误:找不到适合collect的方法(Averager::new、Averager::addcount、Averager::combine) .collect(Averager::new、Averager::addcount、Averager::combine); ^ 方法Stream.collect(供应商、双消费者、双消费者)不适用 (无法推断类型变量R#1 (参数不匹配;方法引用无效。) 找不到符号 符号:方法addcount(R#1,整数) 位置:类别平均值) 方法Stream.collect(收集器)不适用 (无法推断类型变量R#2,A (实际参数列表和正式参数列表长度不同)) 其中R#1,T,R#2,A是类型变量: R#1扩展了方法collect中声明的对象(Supplier、BiConsumer、BiConsumer) T扩展接口流中声明的对象 R#2扩展方法collect(收集器)中声明的对象 方法collect(收集器)中声明的扩展对象 1错误 请帮我理解

Averager averageCollect = zahlen.stream()
  .collect(Averager::new, Averager::addcount, Averager::combine);
这很好。相当于

Averager averageCollect = zahlen.stream()
  .collect(() -> new Averager(),
           (myAverager, n) -> myAverager.addcount(n),
           (dst, src) -> dst.combine(src))
记住,每个非静态方法都有一个隐藏的
参数。在这种情况下,它(正确地)将其绑定到
累加器
组合器
回调的第一个参数

它还可用于静态方法,例如:

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;
}
希望这能让事情变得更清楚

但是不需要更改代码。

当前项可以是第一个参数。因此,一个
BiConsumer
可以为一个
静态
方法提供
方法(a,b)
,或者为一个实例方法提供
a.method(b)
。在你破碎的例子中;您已经传递了一个实例方法。另请参见,特别是“方法引用的种类”一节。
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;
}