1.9.3 완전성 보장하기
스위치 표현식에서 완전성(exhaustiveness)을 보장하는 것은 매우 중요합니다. 이는 모든 가능한 경우를 다루어 코드의 안정성과 신뢰성을 높이는 데 도움이 됩니다.
완전성의 중요성
- 버그 방지: 예상치 못한 입력이나 상태에 대한 대비책을 마련합니다.
- 코드 안정성: 모든 가능한 시나리오를 고려하여 코드의 안정성을 높입니다.
- 유지보수 용이성: 코드의 완전성을 보장함으로써 향후 변경에 대한 준비를 합니다.
기본 클로즈 사용 예시
enum Direction { NORTH, SOUTH, EAST, WEST }
Direction direction = Direction.NORTH;
String directionName = switch (direction) {
case NORTH -> "북쪽";
case SOUTH -> "남쪽";
case EAST -> "동쪽";
case WEST -> "서쪽";
default -> "알 수 없는 방향"; // 기본 클로즈
};
System.out.println(directionName);
이 예제에서:
- 모든 Direction 열거형 값에 대해 명시적인 case가 있습니다.
- default 클로즈는 예상치 못한 값에 대한 대비책으로 사용됩니다.
열거형 타입에서의 자동 완전성
열거형 타입을 사용할 때는 특별한 경우가 있습니다:
enum Season { SPRING, SUMMER, AUTUMN, WINTER }
Season season = Season.SPRING;
String seasonDescription = switch (season) {
case SPRING -> "봄 - 따뜻하고 햇살이 좋은 계절";
case SUMMER -> "여름 - 더운 날씨와 휴가철";
case AUTUMN -> "가을 - 낙엽과 추억의 계절";
case WINTER -> "겨울 - 눈꽃과 추위의 계절";
};
System.out.println(seasonDescription);
이 예제에서:
- 모든 Season 열거형 값에 대해 명시적인 case가 있습니다.
- default 클로즈가 필요 없습니다. 컴파일러가 자동으로 완전성을 보장합니다.
컴파일러의 자동 완전성 보장
열거형 타입의 경우, 컴파일러가 자동으로 완전성을 보장합니다:
enum Status { ACTIVE, INACTIVE }
Status status = Status.ACTIVE;
String statusMessage = switch (status) {
case ACTIVE -> "활성화됨";
case INACTIVE -> "비활성화됨";
};
System.out.println(statusMessage);
이 예제에서:
- 모든 Status 열거형 값에 대해 명시적인 case가 있습니다.
- default 클로즈가 필요 없습니다. 컴파일러가 자동으로 완전성을 보장합니다.
- 만약 새로운 열거형 값이 추가되고 이 스위치 표현식이 업데이트되지 않으면, 런타임에 IncompatibleClassChangeError가 발생합니다.
장점
- 코드 안정성: 모든 가능한 경우를 다루어 코드의 안정성을 높입니다.
- 버그 방지: 예상치 못한 입력이나 상태에 대한 대비책을 마련할 수 있습니다.
- 유지보수 용이성: 코드의 완전성을 보장함으로써 향후 변경에 대한 준비를 합니다.
주의사항
- 열거형 타입이 아닌 경우에는 반드시 default 클로즈를 포함해야 합니다.
- 열거형 타입의 경우에도 default 클로즈를 명시적으로 포함하는 것이 좋습니다. 이는 향후 열거형 값이 추가될 때 컴파일 시 오류를 발생시키므로 버그를 조기에 발견할 수 있습니다.
전통적인 케이스 블록을 사용한 스위치 표현식
스위치 표현식에서는 전통적인 케이스 블록(case block)을 사용할 수도 있습니다. 이 방식은 기존의 스위치 문과 유사하지만, 몇 가지 중요한 차이점이 있습니다.
전통적 케이스 블록의 특징
- 콜론(:) 사용: 각 case 뒤에 콜론을 사용합니다.
- fall-through 동작: 기본적으로 fall-through가 적용됩니다.
- yield 키워드 사용: 값 반환 시
yield
키워드를 사용합니다.
간단한 예시
enum Season { SPRING, SUMMER, AUTUMN, WINTER }
Season season = Season.SPRING;
String seasonDescription = switch (season) {
case SPRING : yield "봄 - 따뜻하고 햇살이 좋은 계절";
case SUMMER : yield "여름 - 더운 날씨와 휴가철";
case AUTUMN : yield "가을 - 낙엽과 추억의 계절";
case WINTER : yield "겨울 - 눈꽃과 추위의 계절";
};
System.out.println(seasonDescription);
이 예제에서:
- 각 case 뒤에 콜론(:)을 사용합니다.
- yield 키워드를 사용하여 값을 반환합니다.
- 모든 가능한 경우를 다루므로 default 케이스가 필요하지 않습니다.
복잡한 로직에서의 활용
복잡한 상황에서는 다음과 같이 사용할 수 있습니다:
enum ProductType { ELECTRONICS, FURNITURE, CLOTHING }
ProductType product = ProductType.ELECTRONICS;
double taxRate = switch (product) {
case ELECTRONICS :
System.out.println("전자제품의 세금 계산 중...");
yield calculateElectronicsTax();
case FURNITURE :
System.out.println("가구의 세금 계산 중...");
yield calculateFurnitureTax();
default :
System.out.println("알 수 없는 제품 타입");
yield 0.10;
};
System.out.printf("세금율: %.2f%%\n", taxRate * 100);
이 예제에서:
- 각 case에 대해 추가적인 로직을 수행할 수 있습니다.
- yield 키워드를 사용하여 최종 결과를 반환합니다.
- default 케이스를 포함하여 모든 가능한 상황을 다룹니다.
장점
- 유연성: 복잡한 로직을 쉽게 구현할 수 있습니다.
- 가독성: 여러 문장을 포함할 수 있어 복잡한 조건을 명확히 표현할 수 있습니다.
- 기존 코드와의 호환성: 기존 스위치 문과 유사한 구조로 전환하기 쉬습니다.
주의사항
- yield 키워드 없이 값을 반환하면 컴파일 오류가 발생합니다.
- fall-through 동작을 원하지 않는다면 각 case 끝에 break를 명시적으로 사용해야 합니다.
- 너무 복잡한 로직은 별도의 메서드로 분리하는 것이 코드 가독성을 높이는 데 도움이 될 수 있습니다.
편히 모아진 글 보시려면 아래 위키독스 링크 >>
https://wikidocs.net/book/17111
'JAVA' 카테고리의 다른 글
JAVA: switch - null 값 처리 [코딩백과 with JAVA] (1) | 2024.12.22 |
---|---|
JAVA: switch 표현식의 값 생성[코딩백과 with JAVA] (0) | 2024.12.22 |
JAVA: Case에 String 타입 사용, Null 선택자 변수[코딩백과 with JAVA] (0) | 2024.12.22 |
JAVA: Switch문과 If-then-else 선택 [코딩백과 with JAVA] (0) | 2024.12.22 |
JAVA Switch문 [코딩백과 with JAVA] (0) | 2024.12.22 |