Java에서 람다를 다루기 위한 노력
public interface FruieFilter {
boolean isSelected(Fruit fruit)
}
private List<Fruit> filterFruits(List<Fruit> fruits, FruitFilter fruitFilter){
//for문 순회, 조건문 체크
}
->
filterFruits(fruits, new FruitFilter() {
@Override
public boolean isSelected(Fruit fruit) {
return //....
}
}
->
private List<Fruit> filterFruits(List<Fruit> fruits, Predicate<Fruit> fruitFilter){
//for문 순회, 조건문 체크
//....
}
filterFruits(fruits, fruit -> fruit.getName().equals(""))
->
private List<Fruit> filterFruits(List<Fruit> fruits, Predicate<Fruit> fruitFilter){
return fruits.stream() .....// stream 사용
}
filterFruits(fruits, Fruit::isApple); // 메소드 레퍼런스
- 인터페이스와 익명 클래스를 통해 무수한 새로운 메소드 생성을 막지만 불편하고 복잡함
- 람다와 스트림이 등장하고 메소드 레퍼런스로 메소드 자체를 직접 넘겨준는 것 처럼 쓸 수 있음
코틀린에서의 람다
- 코틀린에서는 함수가 그 자체로 값이 될 수 있음
- 변수에 할당할 수도, 파라미터로 넘길 수 있음
// predicate을 사용하지 않는다.
private fun filterFruits(fruits: List<Fruit>, filter: (Fruit) -> Boolean: List<Fruit> {
val results = mutableListOf<Fruit>()
for (fruit in fruits) {
if (filter.invoke(fruit)) {
results.add(fruit)
}
}
return results
}
filterFruits(fruits) {it.name == "apple"} // 람다의 파라미터를 it으로 직접 참조
filterFruits(fruits) {fruit ->
println("apple come")
fruit.name == "apple"
}
// 마지막 파라미터가 함수인 경우, 소괄호 밖에 람다 사용 가능
// 람다를 여러줄 작성할 수 있고, 마지막 줄의 결과가 람다의 반환값임
Closure
Java
String FruitName = "banana";
FruitName = "apple"
filterFruits(fruits, (fruit) -> FriutName.equals(fruit.getName())); // 에러 발생
Variable used in lambda expression should be final or effectively final
- Java에서 람다를 쓸 때 사용할 수 있는 변수에 제약이 있음
Kotlin
var fruitName = "banana"
fruitName = "apple"
filterFruits(fruits) { it.name = fruitName }
- 코틀린에서는 아무런 문제 없이 동작함
- 코틀린에서는 람다가 시작하는 지점에 참조하고 있는 변수들을 모두 포획하여 그 정보를 가지고 있다.
- 이러한 구조를 Closure라고 함
다시 try with resources