Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Java Lambda Method Reference: Complete Guide with Examples

Tech 2

In methods requiring functional parameters, you can directly pass another method of the same functional type—this is called method reference binding, similar to function pointers in C. Lambda expressions can replace method references; alternatively, method references are a special case of lambdas that do not allow control over passed arguments.

Constructor Reference

private Employee createEmployee(Supplier<Employee> supplier) {
    return supplier.get();
}

@Test
public void testConstructorReference() {
    Employee emp = createEmployee(Employee::new);
    System.out.println(emp);
}

Requires a no-argument constructor.

Static Method Reference

private static void log(String message) {
    System.out.println(message);
}

@Test
public void testStaticReference() {
    Arrays.asList("aa", "bb", "cc").forEach(MethodRefDemo::log);
}

Simple: ensure the static method’s parameter list matches the required Functional Interface (FI) parameters.

Instance Method Reference

@Test
public void testInstanceMethodReference() {
    Arrays.asList("aa", "bb", "cc").forEach(System.out::println);
}

Simple: ensure the instance method’s parameter list matches the required FI parameters.

Arbitrary Object’s Instance Method Reference (Tricky)

@Test
public void testArbitraryObjectReference() {
    String[] strings = {"zzaa", "xxbb", "yycc"};
    Arrays.sort(strings, String::compareToIgnoreCase);
    System.out.println(Arrays.asList(strings));
    File[] hiddenFiles = new File("C:").listFiles(File::isHidden);
}

Consider itnernal classes:

@Data
public static class Employee {
    private String name;
    private Integer age;

    public int compareByAge(Employee other) {
        return other.getAge() - this.getAge();
    }
    public void print() {
        System.out.println(this);
    }
    public void printEmployee(Employee other) {
        System.out.println(other);
    }
    public int compareTwoEmployees(Employee emp1, Employee emp2) {
        return emp1.getAge().compareTo(emp2.getAge());
    }
}

public static class AnotherEmployee {
    public void print() {
        System.out.println(this);
    }
    public void printEmployee(Employee other) {
        System.out.println(other);
    }
}

Test code:

@Test
public void testArbitraryObjectReference2() {
    Function<String, String> toUpper1 = String::toUpperCase;
    UnaryOperator<String> toUpper2 = x -> x.toUpperCase();

    class Printer {
        public void printMessage(String s) {
            System.out.println(s);
        }
    }
    Consumer<String> printer1 = new Printer()::printMessage;
    Consumer<String> printer2 = x -> new Printer().printMessage(x);

    Employee[] employees = {new Employee(), new Employee()};
    Arrays.sort(employees, Employee::compareByAge);
    Arrays.sort(employees, (x, y) -> x.compareByAge(y));

    Arrays.sort(employees, new Employee()::compareTwoEmployees);
    Arrays.sort(employees, (x, y) -> new Employee().compareTwoEmployees(x, y));

    Comparator<Employee> comparator1 = new Employee()::compareTwoEmployees;
    Comparator<Employee> comparator2 = Employee::compareByAge;
}

Summary:

  1. Static method reference: if the passed method is a type’s static method with matching parameters.
  2. Instance method reference: if the passed method is an instance’s member method with matching parameters.
  3. Arbitrary object’s instance method reference: if the passed method is a member method of type T with N-1 parameters (matching the FI’s required N parameters), the omitted parameter must be of type T (and the method reference prefix must be T’s class name).

Analysis of Omitted Parameter

Define a FI:

public interface CustomFunctionalInterface {
    void process(TestBeanA beanA, TestBeanB beanB);
}

TestBeanA:

public class TestBeanA {
    public void handleA(TestBeanA bean) {}
    public void handleB(TestBeanB bean) {}
    public void execute(CustomFunctionalInterface fi) {}
}

TestBeanB:

public class TestBeanB {
    public void handleA(TestBeanA bean) {}
    public void handleB(TestBeanB bean) {}
    public void execute(CustomFunctionalInterface fi) {}
}

Test code:

public class MethodRefDemo {
    public static void main(String[] args) {
        TestBeanA beanA = new TestBeanA();
        beanA.execute(TestBeanA::handleB); // OK
        beanA.execute(TestBean2::handleA); // Error
    }
}

Key observation: For a FI method with (T1, T2) parameters, only the first parameter (T1) can be omitted. The method reference prefix must be T1’s class name, which the lambda automatically instantiates as the omitted parameter.

Tags: JavaLambda

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.