java - Use of double colons - difference between static and non-static method references -


this question has answer here:

edit: question here answered. summarize, confused usage of non-static method references. there functional interface , referenced method have different number of parameters.

what answered question comment , accepted answer.


i reading java tutorial stream reduction methods (https://docs.oracle.com/javase/tutorial/collections/streams/reduction.html). there found piece of code thought wrong, made simpler code make sure.

// 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 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;     } } 

the reason thought wouldn't work because of line:

averager averagecollect = zahlen.stream()   .collect(averager::new, averager::addcount, averager::combine); 

in java documentation stream.collect (https://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-) says second parameter function matches functional interface biconsumer required has abstract method 2 arguments. averager.addcount , averager.combine have 1 parameter.

i checked lambda expressions:

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

this code works , second , third parameter have functions 2 parameters.

why code wrote above work, though functions 1 parameter given? , why there error messages when change both averager.addcount , averager.combine have 2 parameters this?

public void addcount(averager one, integer i) public void combine(averager one, averager other) 

if following error message:

b.java:12: error: no suitable method found collect(averager::new,averager::addcount,averager::combine)       .collect(averager::new, averager::addcount, averager::combine);       ^     method stream.collect(supplier,biconsumer,biconsumer) 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) not applicable       (cannot infer type-variable(s) r#2,a         (actual , formal argument lists differ in length))   r#1,t,r#2,a 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)     extends object declared in method collect(collector) 1 error

please me understand.

averager averagecollect = zahlen.stream()   .collect(averager::new, averager::addcount, averager::combine); 

this fine. equivalent to

averager averagecollect = zahlen.stream()   .collect(() -> new averager(),            (myaverager, n) -> myaverager.addcount(n),            (dst, src) -> dst.combine(src)) 

remember every nonstatic method has hidden this parameter. in case (correctly) binding first argument of accumulator , combiner callbacks.

it work static methods such as:

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; } 

which makes clearer happening.

but there no need change code.


Comments