Java 8 Method Reference (Phần 2)

phần 1, mình đã giới thiệu qua 2 loại method preference - Method reference một static method - Method reference một instance method của một object có kiểu đặc biệt Giờ chúng ta sẽ tìm hiểu nốt 2 loại còn lại

Method reference một instance method của một object đã tồn tại.

Trong trường hợp này, ta có một lambda expression như sau (args) -> obj.instanceMethod(args) Ta có chuyển thành method reference như sau obj::instanceMethod Lúc này, một instance xác định được sử dụng và nếu có argument thì sẽ được truyền ẩn như trường hợp của method static

class Car {
  private int id;
  private String color;
}
class Mechanic {
  public void fix(Car c) {
    System.out.println("Fixing car " + c.getId());
  }
}

Ta có phương thức

public void execute(Car car, Consumer<Car> c) {
  c.accept(car);
}

Ta có thể gọi phương thức trên bằng cách sau

final Mechanic mechanic = new Mechanic();
Car car = new Car();

// Sử dụng anonymous class
execute(car, new Consumer<Car>() {
  public void accept(Car c) {
    mechanic.fix(c);
  }
});

// Sử dụng lambda expression
execute(car, c -> mechanic.fix(c));

// Sử dụng method reference
execute(car, mechanic::fix);

Mấu chốt ở trường hợp này là sử dụng bất kì object nào bằng anonymous class hoặc lambda expression và truyền argument cho instance method của object đó Một ví dụ khác của việc sử dụng Consumer

Consumer<String> c = System.out::println;
c.accept("Hello");

Constructor method reference

Ở trường hợp này, ta có lambda expression như sau (args) -> new ClassName(args) Ta có thể chuyển thành method reference như sau ClassName::new Lamda expression tạo một object mới và ta chỉ cần reference constructor của class đó với từ khóa “new”. Ở trường hợp này, argument không được truyền trong method reference Hầu hết chúng ta sử dụng cú pháp này với 2 hoặc 3 interface trong java.util.function package Nếu constructor không nhân argument nào, ta sử dụng một Supplier

// Sử dụng anonymous class
Supplier<List<String>> s = new Supplier() {
  public List<String> get() {
    return new ArrayList<String>();
  }
};
List<String> l = s.get();

// Sử dụng lambda expression
Supplier<List<String>> s = () -> new ArrayList<String>();
List<String> l = s.get();

// Sử dụng method reference
Supplier<List::new;
List<String> l = s.get();

Nếu constructor nhận một argument, ta sử dụng Function interface.

// Sử dụng  anonymous class
Function<String, Integer> f =
  new Function<String, Integer>() {
    public Integer apply(String s) {
      return new Integer(s);
    }
};
Integer i = f.apply(100);

//Sử dụng  lambda expression
Function<String, Integer> f = s -> new Integer(s);
Integer i = f.apply(100);

// Sử dụng method reference
Function<String, Integer> f = Integer::new;
Integer i = f.apply(100);

Nếu constructor nhận 2 argument. ta sử dụng BiFunction interface

// Sử dụng  anonymous class
BiFunction<String, String, Locale> f = new BiFunction<String, String, Locale>() {
  public Locale apply(String lang, String country) {
    return new Locale(lang, country);
  }
};
Locale loc = f.apply("en","UK");

// Sử dụng  lambda expression
BiFunction<String, String, Locale> f = (lang, country) -> new Locale(lang, country);
Locale loc = f.apply("en","UK");

// Sử dụng  method reference
BiFunction<String, String, Locale> f = Locale::new;
Locale loc = f.apply("en","UK");

Nếu constructor cần nhiều hơn 2 argument thi ta cần viết custom interface theo nhu cầu của mình Nhìn chung, reference một constructor cũng tương tự việc reference một static method. Khác biệt ở đây là method name của constructor là “new”

Kết luận

Như đã giới thiệu lúc đâu, hãy sử dụng method reference nếu chúng giúp code bạn rõ ràng hơn. Ví dụ ta có thể tránh được việc viết nhiều code trong một method bằng cách nhóm code vào 1 static method và tạo reference đến method thay vì phải gọi class chứa nó hay dùng lambda expression. Tuy nhiên method reference chỉ thực sự hiệu quả và sử dụng được hết tính năng của nó chỉ khi kết hợp với một tính năng mới trong java 8 đó là streams Cảm ơn các bạn đã theo dõi

Bài viết được dịch từ link


All Rights Reserved