
람다식을 알기전에, 배경지식으로 반드시 알아야 할 내용이 바로 익명 클래스다.
익명 클래스 (Annoymous Class)
익명 클래스는 내부 클래스(Inner class) 일종으로 단어 그대로 이름이 없는 클래스다.
익명, 이름이 없다는 것은 알 필요가 없다는 것이며, 나중에 재사용될 일이 없다는 뜻을 지닌다. 즉, 프로그램에서 일시적으로 한 번만 사용되고 버려지는 객체라고 보면 된다. (일회용 클래스)
익명 클래스와 일반 클래스의 사용 예제
// 부모 클래스
class Greeting {
void sayHello() {
System.out.println("안녕하세요!");
}
}
// 자식 클래스, 별도의 클래스 정의
class EnglishGreeting extends Greeting {
@Override
void sayHello() {
System.out.println("Hello, 일반 클래스!");
}
}
public class Main {
public static void main(String[] args) {
Greeting myGreeting = new EnglishGreeting();
myGreeting.sayHello(); // 출력: Hello, 일반 클래스!
}
// 익명 클래스를 사용하여 Greeting을 확장
Greeting anonymousGreeting = new Greeting() {
@Override
void sayHello() {
System.out.println("Hello, 익명 클래스!");
}
};
anonymousGreeting.sayHello(); // 출력: Hello, 익명 클래스!
}
}
익명 클래스와 일반 클래스의 생김새는 유사하지만, 그 사용성에 따라 선택이 달라진다.
보통 어느 클래스의 자원을 상속 받아 재정의하여 사용하기 위해서는 먼저 자식이 될 클래스를 만들고 상속한 후에 객체 인스턴스 초기화를 통해 가능하다. 하지만, 익명 클래스는 클래스 정의와 동시에 객체를 생성할 수 있다.
따로 클래스 정의 없이 메소드 내에서 바로 클래스를 생성해 인스턴스화 할 수 있으며, 이렇게 클래스의 선언과 객체의 생성을 동시에 하기 때문에 단 한 번만 사용될 수 있고, 익명으로 정의된 클래스는 일회용으로써 사용되고 버려진다. 그래서 만일 클래스가 한번만 사용되고 버려질 자료형이면, 굳이 상단에 클래스를 정의하기보다는, 지역 변수처럼 익명 클래스로 정의하고 스택이 끝나면 삭제되도록 하는 것이 유지보수면에서나 프로그램 메모리면에서나 이점을 얻을 수 있다.
✅ 정리하자면,
익명 클래스는 재사용할 필요가 없는 일회성 클래스를 굳이 클래스를 정의하고 생성하는 것이 비효율적이기 때문에, 익명 클래스를 통해 코드를 줄이는 일종의 기법이다.
익명 클래스와 람다식
익명 클래스 기법은 복잡한 자바 문법을 간결하게 하는 것에 초점을 둔다. 따라서 람다식 문법과 잘 어울린다.
// 람다 표현식
Calculator calculator1 = (a, b) -> a + b;
// 익명클래스
Calculator calculator1 = new Calculator() {
@Override
public int sum(int a, int b) {
return a + b;
}
};
람다식은 사실 익명함수가 아니라 익명 객체다 !
람다식 (a, b) -> a + b
는 결국 익명 클래스를 생성한 것과 동일한 역할을 한다.
자바에서 람다식은 내부적으로 익명 클래스의 객체로 변환되기 때문에, 익명 함수가 아니라 익명 객체인 것이다
람다식이란 ?
람다 표현식(Lamda expression) 이란 함수형 프로그래밍을 구성하기 위한 함수식이며, 자바의 메소드를 간결한 함수 식으로 표현한 것이다.
자바에서 메서드를 하나 표현하려면 클래스를 정의해야한다. 하지만 람다식으로 표현하면 ㅁ[서드의 이름과 반환값을 생략할 수 있고, 이를 변수에 넣어 자바 코드가 매우 간결해진다.
아래의 내용과 같이 int add(int a, int b) {}
메소드 표현식을, 메서드 타입, 메서드 이름, 매개변수 타입, 중괄호, return 문을 생략하고, 화살표 기호를 넣음으로써 코드를 혁명적으로 함축했음을 볼 수 있다. 이러한 특징으로 람다식을 이름이 없는 함수 익명 함수(anonymous function) 라고도 한다.

- 함수(메서드) 를
식(Expression)
으로 표현한 것 ! - 익명 함수
따라서 람다식을 사용하면 문법이 간결해지고, 컬렉션(Collection)의 요소를 필터링하거나 매핑하여 원하는 결과를 얻기에 용이하다.
❓ 여기서 잠깐 ! 함수와 메서드의 차이는 ?
근본적으로 동일하다. 함수는 일반적인 용어고, 메서드는 객체 지향 개념의 용어다.
함수는 클래스에 독립적이고, 메서드는 클래스에 종속적이다.
함수형 인터페이스란 ?
함수형 인터페이스란 단 하나의 추상 메서드가 선언된 인터페이스를 말한다. 람다식에서는 함수형 인터페이스가 활용된다.
생각해보면, 람다식 자체가 하나의 메서드를 한 줄로 정의하는 표현식이기 때문에 인터페이스에 두 개 이상의 추상 메서드가 들어있다면 이를 구별할 방법이 없기 때문에, 오로지 추상 메서드 한 개만 가진 인터페이스가 람다식의 타겟 타입이 될 수 있다.
예를 들어, 오버로딩(Overloading) 기능을 통해 같은 이름의 sum()
메서드를 여러 형태로 정의한다면 람다 표현식이 어떤 메서드를 구현하는 것인지 명확하지 않아 모호성이 발생할 수 있다.
@FunctionalInterface
내가 정의한 단 하나의 함수적 인터페이스를 만들 때 두 개 이상의 추상 메서드가 선언되지 않도록 컴파일러가 자동으로 체크해주는 어노테이션이 바로 @FunctionalInterface
이다.
@FunctionalInterface // ✅ 함수형 인터페이스 선언
public interface Calculator {
int sum(int a, int b); // ✅ 오직 하나의 추상 메서드만 선언해야합니다.
int sum(int a, int b, int c); // ❌ 선언 불가 에러발생!
}
람다식의 한계
람다식은 긴 자바 코드를 깔끔하게 줄이는데 큰 도움을 주지만, 사용하기 적절하지 않은 순간들이 존재한다.
1️⃣ 람다는 문서화를 할 수 없다.
이름이 없는 함수이므로 메서드나 클래스와 다르게 문서화를 할 수 없다. 따라서 코드 자체로 동작이 명확하게 설명되지 않거나 람다가 길거나 읽기 어렵다면, 쓰지 않는 것이 좋다.
2️⃣ 람다는 디버깅이 까다롭다.
람다식은 익명 객체이므로, 디버깅이 어렵고 스택 트레이스(Stack Trace)가 이해하기 어려울 수 있다.
List<String> list = Arrays.asList("A", "B", "C");
list.forEach(item -> {
if (item.equals("B")) {
throw new RuntimeException("에러 발생");
}
});
람다식은 anonymous class
로 변환되므로, 스택 트레이스에서 해당 오류가 어디서 발생했는지 찾기 어려울 수 있다.
3️⃣ 람다식을 너무 많이 사용하면 코드의 중복이 발생한다.
4️⃣ break
또는 continue
사용 불가능하다.
람다식은 반복문 내부에서 사용되더라도 break
또는 continue
를 직접 사용할 수 없다.
List<String> list = Arrays.asList("A", "B", "C");
list.forEach(item -> {
if (item.equals("B")) {
break; // 컴파일 오류 ❌
}
System.out.println(item);
});
람다식이 아닌 일반 반복문(for-each)를 사용해야 한다.
for (String item : list) {
if (item.equals("B")) {
break; // 정상 작동 ✅
}
System.out.println(item);
}
5️⃣ 재귀로 만들 경우에 부적합하다.
람다식을 통해 재귀함수를 구축하면, 실행조차 안되는 컴파일 에러가 나타난다.
참고자료
'Language > Java' 카테고리의 다른 글
[Java] if-else와 try-catch에 대해서 (0) | 2025.03.14 |
---|---|
[Java] 제네릭(Generic) (0) | 2025.03.06 |
[Java] 기본형과 참조형 (0) | 2025.03.06 |
[Java] 컬렉션 (Collection) (0) | 2025.03.04 |
[Java] 클래스와 데이터 (0) | 2025.02.27 |