본문 바로가기
카테고리 없음

Java - Switch Case 문 잘 다뤄보기

by Nomangs 2022. 7. 7.
반응형

안녕하세요.

프로그래밍을 수행하다보면 Switch-Case 문을 종종 작성할 때가 있는데요.

활용 방안과 JDK 13 부터 변화된 문법도 살펴보도록 하겠습니다.

Switch-Case 문을 잘 활용할 경우

If-Else 구문을 대체할 수 있는 가독성 좋은 코드로 탄생합니다~

 

사용 예

다음과 같은 중첩된 if-else  이 있다고 가정해 보겠습니다 .

public String exampleOfIF(String animal) {
    String result;
    if (animal.equals("DOG") || animal.equals("CAT")) {
        result = "domestic animal";
    } else if (animal.equals("TIGER")) {
        result = "wild animal";
    } else {
        result = "unknown animal";
    }
    return result;
}

위의 코드는 보기에 좋지 않고 유지 관리하고 추론하기 어려울 것입니다.

가독성을 높이기 위해 switch 문을 사용할 수 있습니다.

public String exampleOfSwitch(String animal) {
    String result;
    switch (animal) {
        case "DOG":
            result = "domestic animal"; 
            break;
        case "CAT":
            result = "domestic animal";
            break;
        case "TIGER":
            result = "wild animal";
            break;
        default:
            result = "unknown animal";
            break;
    }
    return result;
}

우리는 switch 인수 animal 을 여러 케이스 값과 비교합니다. 케이스 값 중 인수와 같은 값이 없으면 기본 레이블 아래의 블록이 실행됩니다.

간단히 말해 break 문은 switch 문 을 종료하는 데 사용됩니다 .

 

 break 문

실생활에서 대부분의  switch 문은 case 블록 중 하나만 실행되어야 함을 의미하지만  블록이 완료된 후 스위치 를 종료하려면 break 문을 사용해야 합니다 .

break 를 쓰는 것을 잊었다면  아래 블록이 실행될 것입니다.

이를 보여주기 위해 break  문을 생략하고 각 블록의 콘솔에 출력을 추가해 보겠습니다.

public String forgetBreakInSwitch(String animal) {
    switch (animal) {
    case "DOG":
        System.out.println("domestic animal");
    default:
        System.out.println("unknown animal");
    }
}

이 코드 forgetBreakInSwitch ( "DOG")  를 실행하고 모든 블록이 실행되는지 확인하기 위해 출력을 확인합니다.

domestic animal
unknown animal

따라서 다음 레이블 아래의 코드로 전달할 필요가 없는 한 주의하고 각 블록 끝에 break 문을 추가해야 합니다.

 

break 가 필요하지 않은 유일한 블록  은 마지막 블록  이지만  마지막 블록에 break 를 추가하면 코드에서 오류가 발생하기 쉽습니다.

여러 case 문에 대해 동일한 코드를 실행하려는 경우 이 동작을 활용하여 break 를 생략 할 수도 있습니다.

처음 두 경우를 그룹화하여 이전 섹션의 예를 다시 작성해 보겠습니다.

public String exampleOfSwitch(String animal) {
    String result;
    switch (animal) {
        case "DOG":
        case "CAT":
            result = "domestic animal";
            break;
        case "TIGER":
            result = "wild animal";
            break;
        default:
            result = "unknown animal";
            break;
    }
    return result;
}

인수 및 케이스 값 전환

이제 허용되는 유형의 switch 인수 및 케이스 값, 이에 대한 요구 사항 및  switch 문이 문자열과 함께 작동하는 방식에 대해다뤄봅니다.

데이터 유형

switch 문 에서 모든 유형의 개체와 기본 요소를 비교할 수는 없습니다  . 스위치 는 4개의 프리미티브와 해당 래퍼, enum 유형  및  String 클래스 에서만 작동합니다 .

    byte and Byte
    short and Short
    int and Integer
    char and Character
    enum
    String

문자열  유형은 Java 7부터 switch 문에서 사용할 수 있습니다.
enum 유형은 Java 5에서 도입되었으며 그 이후로 switch 문에서 사용할 수 있습니다.
래퍼 클래스도 Java 5부터 사용할 수 있습니다.
물론 switch 인자와 case 값은 같은 타입이어야 합니다.

 

null 값 없음

null 값을 switch 문의 인수로 전달할 수 없습니다 .

그렇게 하면 프로그램은 첫 번째 스위치  예제 를 사용하여 NullPointerException 을 throw합니다.

@Test(expected=NullPointerException.class)
public void whenSwitchAgumentIsNull_thenNullPointerException() {
    String animal = null;
    Assert.assertEquals("domestic animal", s.exampleOfSwitch(animal));
}

물론 switch 문의 case 레이블에 값으로 null 을 전달할 수도 없습니다. 그렇게 하면 코드가 컴파일되지 않습니다.

 

컴파일 시간 상수로서의 케이스 값

DOG 케이스 값을 dog 변수 로 바꾸려고 하면  dog 변수를  final 로   표시할 때까지 코드가 컴파일되지 않습니다 .

final String dog="DOG";
String cat="CAT";

switch (animal) {
case dog: //compiles
    result = "domestic animal";
case cat: //does not compile
    result = "feline"
}

문자열 비교

switch 문 이 문자열을 비교하기 위해 등호 연산자를  사용한 경우 new 연산자 로  생성 된 String 인수 를 String 케이스 값과 올바르게 비교할 수 없습니다.

운 좋게도  스위치 연산자는 내부적으로 equals() 메서드를 사용합니다.

@Test
public void whenCompareStrings_thenByEqual() {
    String animal = new String("DOG");
    assertEquals("domestic animal", s.exampleOfSwitch(animal));
}

스위치 식

이제 JDK 13 을 사용할 수 있으며 JDK 12 에 처음 도입된 새로운 기능인 스위치 표현식 의 개선된 버전을 제공합니다 .


활성화 하려면 컴파일러에 –enable-preview 를 전달해야 합니다 .

새로운 스위치 표현식

몇 개월에 걸쳐 전환할 때 새로운 switch 표현식이 어떻게 보이는지 봅시다 .

var result = switch(month) {
    case JANUARY, JUNE, JULY -> 3;
    case FEBRUARY, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER -> 1;
    case MARCH, MAY, APRIL, AUGUST -> 2;
    default -> 0; 
};

Month.JUNE 와 같은 값을 보내면 결과 가 3 으로 설정 됩니다 .

새 구문은 우리가 switch 문 에 익숙했던 콜론 대신 -> 연산자를 사용합니다. 또한 break 키워드 가 없습니다. switch 표현식은  case s를 통과하지 않습니다.

또 다른 추가 사항은 이제 쉼표로 구분된 기준을 가질 수 있다는 사실입니다.

 

yield 키워드 _

조금 더 나아가서 코드 블록을 사용하여 표현식의 오른쪽에서 일어나는 일을 세밀하게 제어할 수 있습니다.

이 경우 yield 키워드를 사용해야 합니다 .

var result = switch (month) {
    case JANUARY, JUNE, JULY -> 3;
    case FEBRUARY, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER -> 1;
    case MARCH, MAY, APRIL, AUGUST -> {
        int monthLength = month.toString().length();
        yield monthLength * 4;
    }
    default -> 0;
};

내부 스위치 표현식 반환

switch 문과 switch 식을 구분한 결과로 switch 문 내에서 반환 할 수 있지만 switch 식 내에서 반환 할 수 없습니다 .

다음 예제는 완벽하게 유효하며 컴파일됩니다.

switch (month) {
    case JANUARY, JUNE, JULY -> { return 3; }
    default -> { return 0; }
}

그러나 둘러싸는 스위치 표현식 외부 에서 반환 을 시도하기 때문에 다음 코드는 컴파일되지 않습니다 .

var result = switch (month) {
    case JANUARY, JUNE, JULY -> { return 3; }
    default -> { return 0; }
};

 

반응형

댓글