- JAVA에서 람다를 다루기 위한 노력
- 코틀린에서의 람다
- Closure
- try with resources (use)
| - 함수 : 코틀린에선 1급 시민, 자바에선 2급시민 - 코틀린에서 함수 타입 : (파라미터 타입, ..) -> 반환타입 - 코틀린에서 람다를 사용하는 방법은 두가지 이고 이 중 중괄호 방식이 더 많이 사용된다. - 메서드 호출 시 마지막 파라미터인 람다를 쓸 땐 소괄호 밖으로 람다를 뺄 수 있다 - 파라미터의 함수의 매개값이 한개 라면 it를 사용할 수 있지만 it을 사용하지 않는 것이 코드 가독성이 높다. - 람다 내부에 return을 사용하지 않아도 되지만 이때는 마지막 expression 결과는 람다의 반환 값이다. - Closure를 사용하여 final이 아닌 변수도 코틀린에서 람다로 사용가능하다. |
1 . 자바에서의 람다
- 람다 사용 전 : 필터 요인이 많아질 수록 파라미터가 길어져 장황해진다.
public class Main {
public static void main(String[] args) {
// Fruits - 멤버변수로 name과 price가 있는 객체
List<Fruit> fruits = Arrays.asList(
new Fruit("Apple", 1_000),
new Fruit("Apple", 1_200),
new Fruit("Apple", 1_200),
new Fruit("Apple", 1_500),
new Fruit("Banana", 3_000),
new Fruit("Banana", 3_200),
new Fruit("Banana", 2_500),
new Fruit("watermelon", 13_000));
}
List<Fruit> target(List<Fruit> fruits, String name) {
List<Fruit> result = new ArrayList<>();
for (Fruit fruit : fruits) {
if (fruit.getName().equals(name)) {
result.add(fruit);
}
}
return result;
}
}
→ 익명클래스와 인터페이스를 이용해서 코드의 양을 줄일 수 있다.
// 인터페이스
public interface FruitFilter {
boolean isSelected(Fruit fruit);
}
// FruitFilter 객체
public static List<Fruit> filterFruits(List<Fruit> fruits, FruitFilter filter) {
List<Fruit> result = new ArrayList<>();
return result;
}
// isSelected 오버라이딩
private List<Fruit> fruits;
List<Fruit> result = filterFruits(fruits, new FruitFilter() {
@Override
public boolean isSelected(Fruit fruit) {
return Arrays.asList("Apple", "Banana").contains(fruit.getName())
&& fruit.getPrice() >= 3_000;
}
});
→ 복잡하고 다양한 filter가 필요 할 수 있음
▶ 이에 여러 인터페이스가 필요하게 됨
□ 자바 람다로 리펙토링
(1) 변수 -> 변수를 이용한 함수
- (변수1, 변수2) -> 변수1과 변수2를 이용한 함tn
public class Main {
public static void main(String[] args) {
// Fruits - 멤버변수로 name과 price가 있는 객체
List<Fruit> fruits = Arrays.asList(
new Fruit("Apple", 1_000),
new Fruit("Apple", 1_200),
new Fruit("Apple", 1_200),
new Fruit("Apple", 1_500),
new Fruit("Banana", 3_000),
new Fruit("Banana", 3_200),
new Fruit("Banana", 2_500),
new Fruit("watermelon", 13_000));
List<Fruit> result = filterFruits(fruits
, fruit -> fruit.getName().equals("Apple"));
}
}
(2) Predicate (미리 만들어져 있는 함수형 인터페이스)
package fp;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
public class Fruit {
private final String name;
private final int price;
.....
public List<Fruit> filterFruits2(List<Fruit> fruits, Predicate<Fruit> filter) {
List<Fruit> result = new ArrayList<>();
for(Fruit fruit : fruits) {
if(filter.test(fruit)) {
result.add(fruit);
}
}
return result;
}
}
(3) stream 이용
public List<Fruit> streamFruits(List<Fruit> fruits, Predicate<Fruit> fruitFilter) {
return fruits.stream()
.filter(fruitFilter)
.collect(Collectors.toList());
}
(4) 메서드 레퍼런스 이용
public static boolean isApple(Fruit fruit) {
return fruit.getName().equals("Apple");
}
List<Fruit> result2 = filterFruits(fruits, Fruit::isApple);
→ 메서드 자체를 직접 넘겨주는 '것처럼' 쓸 수 있다. 실제로 받는건 Predicate 인터페이스이다.
▶ 함수를 2급시민으로 간주 : 자바에서 함수는 변수에 직접 할당, 파라미터로 바로 넘길 수 없다.
2 . 코틀린에서의 람다
- (함수를 1급시민으로 간주)
- 코틀린에서는 함수가 그 자체로 값이 될 수 있고, 변수에 할당할수도, 파라미터로 넘길 수도 있다.
package fp
fun main() {
val fruits = listOf(
Fruit("apple", 1_000),
Fruit("apple", 1_200),
Fruit("apple", 1_300),
Fruit("apple", 1_400),
Fruit("apple", 1_500),
Fruit("banana", 2_500),
Fruit("banana", 3_500),
Fruit("watermelon", 13_500),
)
// 함수의 타입을 (매개변수타입) -> 반환타입으로 명시할 수 있다.
// 람다 1 - 이름 빼기
val isApple: (Fruit) -> Boolean = fun(fruit: Fruit): Boolean { // 함수이름 x
return fruit.name == "apple"
}
// 람다 2 - 중괄호와 -> 이용
val isApple2: (Fruit) -> Boolean = { fruit: Fruit -> fruit.name == "apple"}
// 람다 호출 1
isApple(fruits[0])
// 람다 호출 2 invoke로 명시적이게
isApple2.invoke(fruits[1])
}
- filterFruit 구현 : 파라미터에 함수를 넣을 수 있다.
package fp
fun main() {
val fruits = listOf(
...
)
// filterFruit 매개값에 들어가는 변수(함수) 구현
val isApple = fun(fruit: Fruit): Boolean {
return fruit.name == "apple"
}
// filterFruit 호출
filterFruits(fruits, isApple)
}
// 자바 filterFruit를 코틀린으로 구현
private fun filterFruits(
fruits: List<Fruit>, filter: (Fruit) -> Boolean
): List<Fruit> {
val results = mutableListOf<Fruit>()
for (fruit in fruits) {
if (filter(fruit)) {
results.add(fruit)
}
}
return results
}
익명함수이기 때문에 매개값에 함수를 바로 넣어주어도 된다
이 때, 람다를 여러줄 작성할 수 있고, return을 명시하지 않아도 마지막 줄의 결과를 람다의 반환값으로 본다.
filterFruits(fruits, fun(fruit: Fruit): Boolean {
return fruit.name == "apple"
})
또는
filterFruits(fruits,{ fruit: Fruit -> fruit.name == "apple" })
매개값에 변수와 함수를 구분하기 위해 괄호를 구분할 수 있다, 이경우 {}안의 함수는 마지막 인자로 사용된다
또한 람다의 파라미터를 it으로 직접 참고할 수 있다.
filterFruits(fruits){ fruit: Fruit -> fruit.name == "apple" }
// filterFruits에 타입을 명시했기 때문에 위 Fruit 타입도 생략가능하다(타입추론)
filterFruits(fruits){ fruit -> fruit.name == "apple" }
// 타입추론도 가능하고 함수의 파라미터도 하나라면 -> 까지 생략가능하다 (it 키워드 이용)
filterFruits(fruits){ it.name == "apple" }
3 . Closure
- Java에서는 람다를 사용할 때 변수는 final인 변수 혹은 실질적으로 final인 변수만 사용할 수 있는 반면 코틀린에서는 문제없이 작동한다
var targetFruitName = "watermelon"
targetFruitName = "banana"
filterFruits(fruits) { it.name == targetFruitName }
(targetFruitName이 가변이여도 동작함)
□ 코틀린에서는 람다가 시작하는 지점에 참조하는 변수들을 모두 캡쳐함.
이는 코틀린에서 람다를 일급 시민으로 간주하기 위해서이며, 이 데이터 구조를 Closure라고 한다.
4 . try with resources (use)
use 메서드

(1) Closable 구현체의 확장 함수
(2) inline 함수
(3) 받고 있는 파라미터 = block 함수
※ (intellij) 코틀린 코드 자바로 변환
tool > Kotlin > Show Kotlin Bytecode
자바 개발자를 위한 코틀린 입문(Java to Kotlin Starter Guide)| 최태현 - 인프런 강의
현재 평점 5.0점 수강생 3,556명인 강의를 만나보세요. 이 강의를 통해 Kotlin 언어의 특성과 배경, 문법과 동작 원리, 사용 용례, Java와 Kotlin을 함께 사용할 때에 주의할 점 등을 배울 수 있습니다. Ko
www.inflearn.com
'Kotlin > Java to Kotlin Guide' 카테고리의 다른 글
| Type Alias·as import / 구조분해·componentN / Jump·Label / Takeif · TakeUnless (0) | 2025.10.09 |
|---|---|
| FP - 컬렉션을 함수형으로 다루는 방법 (0) | 2025.10.09 |
| FP - 다양한 함수 (0) | 2025.10.09 |
| FP - 배열과 컬렉션 (0) | 2025.10.08 |
| 코틀린에서의 OOP - 6. 다양한 클래스를 다루는 방법 (0) | 2025.10.07 |