Method references allow predefined static or instance methods that adhere to a compatible functional interface to be passed as arguments instead of an anonymous lambda expression.

Assume that we have a model:

class Person {
    private final String name;
    private final String surname;

    public Person(String name, String surname){
        this.name = name;
        this.surname = surname;
    }

    public String getName(){ return name; }
    public String getSurname(){ return surname; }
}
List<Person> people = getSomePeople();

Instance method reference (to an arbitrary instance)

people.stream().map(Person::getName)

The equivalent lambda:

people.stream().map(person -> person.getName())

In this example, a method reference to the instance method getName() of type Person, is being passed. Since it’s known to be of the collection type, the method on the instance (known later) will be invoked.


Instance method reference (to a specific instance)

people.forEach(System.out::println);

Since System.out is an instance of PrintStream, a method reference to this specific instance is being passed as an argument.

The equivalent lambda:

people.forEach(person -> System.out.println(person));

Static method reference

Also for transforming streams we can apply references to static methods:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
numbers.stream().map(String::valueOf)