Using method reference instead of multi argument lambda

SomeClass::func can mean two things, depending on whether func is a static method or an instance method.

(1) If func is a static method, then SomeClass::func is a lambda that just passes all the arguments to the method:

(a, b, c) -> SomeClass.func(a, b, c);

(2) If func is an instance method, then SomeClass::func is a lambda that uses the first argument as the instance, as you thought:

(a, b, c) -> a.func(b, c);

where a has type SomeClass.

EDIT: Sotirios' answer demonstrates yet a different type of method reference: example::method where example is a reference variable (instead of a class name). This means the same as

(a, b) -> example.method(a, b);

or perhaps more accurately

(a, b) -> __someFinalTemporary.method(a, b);

where __someFinalTemporary is assigned to example at the point where the method reference is evaluated, so that if example changes later, the method is still called using the earlier value of example.

[The fourth kind is SomeClass::new which passes the arguments to a constructor. I think that's all of them.]


Here's a small example demonstrating the behavior of an instance method reference.

public class Example {  
    public static void main(String[] args) throws Exception {
        List<String> strings = new ArrayList<String>();
        Example example = new Example();
        Functional methodRef = example::method;
        methodRef.funct("a string", strings);
        System.out.println("List now contains: " + strings);

        Functional lambda = (String s, List<String> l) -> {
            example.method(s, l);
        };
        lambda.funct("another string", strings);
        System.out.println("List now contains: " + strings);
    }

    interface Functional {
        void funct(String value, List<String> list);
    }

    void method(String value, List<String> toAddTo) {
        System.out.println("adding");
        toAddTo.add(value);
    }
}

It prints

adding
List now contains: [a string]
adding
List now contains: [a string, another string]

The two are more or less equivalent. In the lambda's case, the variable the method is invoked on needs to be effectively final.


I mean instead of (a, b, c) -> a.func(b, c) we can write ClassOfA::func

Yes, that's correct.