Method Reference
- 기존에 이미 선언된 메소드를 지정하고 싶을 때 사용한다.
- :: 오퍼레이터를 사용한다.
- 생략되는 부분이 많기 때문에 사용할 메소드의 매개변수의 타입과 리턴 타입을 미리 숙지해야한다.
Method Reference 의 4가지 케이스
- ClassName::staticMethodName (클래스의 static Method 를 지정할 때)
- ObjectName::instanceMethodName (선언된 객체의 instance method 를 지정할 때)
- ClassName::instanceMethodName (객체의 instance method를 지정할 때)
- ClassName::new (클래스의 constructor를 지정할 때)
ClassName::staticMethodName (클래스의 static Method 를 지정할 때)
public class MethodReferenceTypeOne {
public static int calculate(int x, int y, BiFunction<Integer, Integer, Integer> operator) {
return operator.apply(x, y);
}
public static int multiply(int x, int y) {
return x * y;
}
public static void main(String[] args) {
Function<String, Integer> str2int = Integer::parseInt;
System.out.println(str2int.apply("20"));
System.out.println(calculate(8, 2, (x, y) -> x + y)); // BiFuction으로 인자 전달
System.out.println(calculate(8, 2, MethodReferenceTypeOne::multiply));
}
}
- calculate 메소드의 세번째 인자는 BiFunction<Integer, Integer, Integer> 이다. -> 그렇기 때문에 Integer 타입의 인자 2개를 받아서 Integer 타입 1개를 반환하는 multiply 메소드를 변수로 받을 수 있다.
ObjectName::instanceMethodName (선언된 객체의 instance method 를 지정할 때)
public class MethodReferenceTypeTwo {
public static int calculate(int x, int y, BiFunction<Integer, Integer, Integer> operator) {
return operator.apply(x, y);
}
public int subtract(int x, int y) {
return x - y;
}
public void myMethod() {
System.out.println(calculate(10, 3, this::subtract));
}
public static void main(String[] args) {
String str = "hello";
Predicate<String> equalsToHello = str::equals;
System.out.println(equalsToHello.test("world"));
MethodReferenceTypeOne instance = new MethodReferenceTypeOne();
System.out.println(calculate(8, 2, instance::subtract));
instance.myMethod();
}
}
ClassName::instanceMethodName (객체의 instance method를 지정할 때)
public class MethodReferenceTypeThree {
public static void main(String[] args) {
Function<String, Integer> strLength = String::length; // instance method 이다.
int length = strLength.apply("hello world");
System.out.println(length);
BiPredicate<String, String> strEquals = String::equals;
boolean helloEqualsWorld = strEquals.test("hello", "world");
System.out.println(strEquals.test("hello", "hello"));
List<User> users = new ArrayList<>();
users.add(new User(3, "Alice"));
users.add(new User(1, "Charlie"));
users.add(new User(5, "Bob"));
printUserField(users, User::getName);
}
public static void printUserField(List<User> users, Function<User, Object> getter) {
for (User user : users) {
System.out.println(getter.apply(user));
}
}
}
- String 2개를 인자로 받아서 값을 비교하기 때문에 반환 타입이 BiPredicate<String, String> 으로 String::length를 받는다.
ClassName::new (클래스의 constructor를 지정할 때)
public class MethodReferenceTypeFour {
public static void main(String[] args) {
Map<String, BiFunction<String, String, Car>> carTypeToConstructorMap = new HashMap<>();
carTypeToConstructorMap.put("sedan", Sedan::new);
carTypeToConstructorMap.put("suv", Suv::new);
carTypeToConstructorMap.put("van", Van::new);
User user = new User(1, "Alice");
BiFunction<Integer, String, User> userCreator = User::new;
User charlie = userCreator.apply(3, "Charlie");
System.out.println(charlie);
String[][] inputs = new String[][] {
{ "sedan", "Sonata", "Hyundai" },
{ "van", "Sienna", "Toyota" },
{ "sedan", "Model S", "Tesla" },
{ "suv", "Sorento", "KIA" }
};
List<Car> cars = new ArrayList<>();
for (int i = 0; i < inputs.length; i++) {
String[] input = inputs[i];
String carType = input[0];
String name = input[1];
String brand = input[2];
cars.add(carTypeToConstructorMap.get(carType).apply(name, brand));
}
for (Car car : cars) {
car.drive();
}
}
}
- User 의 생성자가 인자 2개를 받아서 객체를 생성하므로 Integer와 String 을 인자로 받아서 User 를 반환할 수 있는 타입인 BiFunction<Integer, String, User> 타입으로 User::new 생성자를 받는다.
REFERENCES