이번 글은 Java 21에서 가장 혁신적인 문법 중 하나이다.
많은 사람들이
"switch에서 타입을 비교할 수 있네?"
정도로만 이해하지만,
실제로는 객체지향 코드의 if-else 체인을 크게 줄여주는 기능이며,
이후 배울 record, sealed class와 만나면 Java가 함수형 스타일에 가까워지는 이유를 이해하게 된다.
Pattern Matching for switch(Java 21)
switch에서 값뿐만 아니라 타입(Type)까지 검사하고, 동시에 형변환(Casting)까지 수행하는 문법
기존 Java는 어떻게 작성했을까?
예를 들어 Object가 하나 들어온다고 가정하자.
public void print(Object obj) {
}
이 객체가
String
Integer
User
중 무엇인지 확인해야 한다.
기존 방식은
if (obj instanceof String) {
String str = (String) obj;
System.out.println(str);
}
else if (obj instanceof Integer) {
Integer number = (Integer) obj;
System.out.println(number);
}
else {
System.out.println("Unknown");
}
문제가 무엇일까?
같은 타입을 두 번 적는다.
obj instanceof String
↓
(String) obj
Java 16에서 먼저 개선되었다.
instanceof Pattern Matching
if (obj instanceof String str) {
System.out.println(str);
}
여기서
instanceof
↓
타입 검사
↓
자동 형변환
↓
지역 변수 생성
까지 한 번에 수행한다.
그런데 분기가 많아지면?
if (obj instanceof String str) {
}
else if (obj instanceof Integer number) {
}
else if (obj instanceof User user) {
}
else if (obj instanceof Product product) {
}
if-else가 계속 길어진다.
그래서 switch에도 Pattern Matching이 추가되었다.
switch (obj) {
case String str ->
System.out.println(str);
case Integer number ->
System.out.println(number);
default ->
System.out.println("Unknown");
}
정말 중요한 점은
case String str
↓
String인지 검사
↓
자동 캐스팅
↓
str 변수 생성
까지 수행한다는 것이다.
기존 코드와 비교
기존
if (obj instanceof User) {
User user = (User) obj;
System.out.println(user.getName());
}
Pattern Matching
switch (obj) {
case User user ->
System.out.println(user.getName());
default -> {
}
}
캐스팅 코드가 사라진다.
실제 실행 흐름
Object obj = "Hello";
switch
switch (obj) {
case String str -> ...
case Integer number -> ...
}
실행
Object
↓
String인가?
↓
YES
↓
자동 캐스팅
↓
String str 생성
↓
case 실행
여러 타입 처리
switch (obj) {
case String str ->
System.out.println(str);
case Integer number ->
System.out.println(number);
case Double value ->
System.out.println(value);
default ->
System.out.println("Unknown");
}
switch 하나로
타입 검사
↓
캐스팅
↓
실행
을 모두 처리한다.
when 조건(Guarded Pattern)
타입만으로 부족할 수도 있다.
예를 들어
String인데 길이에 따라 분기하고 싶다.
switch (obj) {
case String str when str.length() > 10 ->
System.out.println("Long String");
case String str ->
System.out.println("Short String");
default ->
System.out.println("Unknown");
}
실행 순서
String인가?
↓
YES
↓
when 조건 확인
↓
true
↓
실행
null도 처리 가능하다.
기존 switch
switch (obj) {
}
obj가 null이면
NullPointerException
이었다.
Pattern Matching switch
switch (obj) {
case null ->
System.out.println("Null");
case String str ->
System.out.println(str);
default ->
System.out.println("Other");
}
null도 하나의 case로 처리할 수 있다.
왜 이 기능이 중요한가?
예를 들어
결제 시스템
Payment
↓
CardPayment
↓
CashPayment
↓
PointPayment
기존
if (payment instanceof CardPayment) {
}
else if (payment instanceof CashPayment) {
}
else if (payment instanceof PointPayment) {
}
Pattern Matching
switch (payment) {
case CardPayment card -> ...
case CashPayment cash -> ...
case PointPayment point -> ...
}
객체지향 코드가 훨씬 읽기 쉬워진다.
record와 만나면 더 강력해진다.
다음 글에서 배울
record User(
String name,
int age
) {
}
가 있다고 하자.
Pattern Matching
switch (obj) {
case User user ->
System.out.println(user.name());
default -> {
}
}
더 이상
(User) obj
같은 캐스팅이 필요 없다.
sealed class와 만나면 더 강력하다.
sealed interface Shape
permits Circle, Rectangle {
}
Pattern Matching
return switch (shape) {
case Circle c -> ...
case Rectangle r -> ...
};
컴파일러는
Circle
Rectangle
둘 다 처리 완료
↓
default 필요 없음
을 알 수 있다.
즉,
컴파일러가
"모든 경우를 처리했는지"
검사할 수 있게 된다.
실무에서 사용 예
API 응답 처리
switch (response) {
case SuccessResponse success -> ...
case ErrorResponse error -> ...
}
이벤트 처리
switch (event) {
case LoginEvent login -> ...
case LogoutEvent logout -> ...
case OrderEvent order -> ...
}
메시지 처리
switch (message) {
case TextMessage text -> ...
case ImageMessage image -> ...
case VideoMessage video -> ...
}
장점
instanceof 제거
↓
형변환 제거
↓
가독성 향상
↓
컴파일러 타입 검사 강화
↓
record / sealed class와 최고의 궁합
언제 사용하면 좋을까?
추천
- 여러 타입 분기
- 이벤트 처리
- DTO 처리
- AST(Abstract Syntax Tree)
- sealed class 계층
추천하지 않는 경우
switch (status) {
case 1 -> ...
case 2 -> ...
}
처럼
단순 숫자 비교는 일반 Switch Expression이 더 직관적이다.
면접 포인트
Pattern Matching for switch란?
switch에서 타입 검사와 자동 형변환을 동시에 수행할 수 있도록 만든 Java 21 문법이다.
기존 방식과 차이점은?
기존
if (obj instanceof User) {
User user = (User) obj;
}
↓
새로운 방식
case User user ->
장점은?
- 캐스팅 코드 제거
- 가독성 향상
- 타입 안전성 증가
- record, sealed class와 자연스럽게 결합
다음 글
다음은 record(Java 16) 이다.
여기서는
- DTO에 getter, equals(), hashCode(), toString()을 왜 매번 만들었는지
- record가 왜 immutable인지
- Lombok의 @Data, @Value와 무엇이 다른지
- Spring Boot에서 Request/Response DTO로 record를 많이 사용하는 이유
까지 실무 관점에서 깊이 있게 설명하겠다.
'language > java' 카테고리의 다른 글
| sealed class(Java 17) (0) | 2026.06.17 |
|---|---|
| record(Java 16) (0) | 2026.06.17 |
| Switch Expression(Java 14) (0) | 2026.06.17 |
| Text Block(Java 15) (0) | 2026.06.17 |
| var 키워드 (0) | 2026.06.17 |
댓글