JavaRush /Java Blog /Random-KO /Java의 스위치 문

Java의 스위치 문

Random-KO 그룹에 게시되었습니다
당신이 유명한 그림에 나오는 영웅처럼 갈림길에 서 있다고 상상해 보세요. 왼쪽으로 가면 말을 잃을 것이고, 오른쪽으로 가면 지식을 얻을 것이다. 그러한 상황을 프로그래밍하는 방법은 무엇입니까? if-thenif-then-else 구문을 사용하여 그러한 선택을 한다는 것을 이미 알고 계실 것입니다 .
if (turn_left) {
    System.out.println(«Коня потеряешь»);
}
if (turn_right) {
    System.out.println(“Знания обретёшь”);
}
else
    System.out.println(“Так и будешь стоять?);
그러한 트랙이 2개가 아니라 10개라면 어떻게 될까요? "오른쪽으로", "조금 왼쪽으로", "조금 더 왼쪽으로" 등 10개의 경로가 있나요? 이 버전에서 if-then-else 코드가 어떻게 커질지 상상해 보세요!
if (вариант1)
{}
else if (вариант2)
{}else if (вариантN).
따라서 하나의 조건 포크가 아니라 여러 개(예: 10개)가 있습니다(여기서 중요한 것은 포크 수가 제한되어 있다는 것입니다). 이러한 상황에서는 특별한 선택 연산자인 스위치 케이스 java가 있습니다 .
switch (ВыражениеДляВыбора) {
           case  (Значение1):
               Код1;
               break;
           case (Значение2):
               Код2;
               break;
...
           case (ЗначениеN):
               КодN;
               break;
           default:
               КодВыбораПоУмолчанию;
               break;
       }
명령문의 실행 순서는 다음과 같습니다.
  • SelectionExpression이 평가됩니다. 다음으로, switch 문은 결과 표현식을 다음 값(나열된 순서대로)과 비교합니다.
  • SelectExpression이 값과 일치하면 콜론 뒤의 코드가 실행됩니다.
  • break 구문이 발견 되면 제어는 스위치 명령 외부로 전송됩니다.
  • ExpressionForSelection과 Values ​​사이에 일치하는 항목이 없으면 제어가 DefaultSelectionCode로 전송됩니다.
중요사항
  • Java의 스위치 선택 문의 SelectionExpression 유형은 다음 중 하나여야 합니다.

    • 바이트 , 짧은 , 문자 , int .
    • 래퍼는 Byte , Short , Character , Integer 입니다 .
    • 문자열 (Java 7부터).
    • 열거형( Enum ).
  • 기본 블록은 선택 사항이며 SelectionExpression과 값이 일치하지 않으면 아무 작업도 수행되지 않습니다.
  • break 는 선택 사항이며, 존재하지 않는 경우 첫 번째 breakswitch 문이 나타날 때까지 또는 끝날 때까지 코드가 계속 실행됩니다(case 블록의 값에 대한 추가 비교를 무시함).
  • 여러 선택 옵션에 대해 동일한 코드를 실행해야 하는 경우 중복을 피하기 위해 연속된 케이스 블록 에서 해당 코드 앞에 여러 해당 값을 표시합니다 .

Java에서 스위치 문을 사용하는 연습으로 넘어 갑시다

걱정하지 마십시오. 이론은 끝났습니다. 추가 예제를 보면 모든 것이 훨씬 더 명확해질 것입니다. 그럼 시작해 보겠습니다. 태양계 행성에 대한 천문학의 예를 살펴 보겠습니다. 최신 국제 규정에 따라 명왕성은 궤도 특성으로 인해 제외됩니다. 우리 행성은 태양으로부터 수성, 금성, 지구, 화성, 목성, 토성, 천왕성, 해왕성 순서로 위치한다는 것을 기억합시다. 행성의 일련 번호(태양으로부터의 거리에 상대적)를 입력으로 받고 출력으로 이 행성 대기의 주요 구성을 List <String> 형식으로 생성하는 Java 메서드를 만들어 보겠습니다 . 일부 행성은 비슷한 대기 구성을 가지고 있음을 상기시켜 드리겠습니다. 따라서 금성과 화성은 주로 이산화탄소를 함유하고 있고 목성과 토성은 수소와 헬륨으로 구성되어 있으며 천왕성과 해왕성에는 마지막 가스 쌍 외에 메탄도 함유되어 있습니다. 우리의 기능:
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
            break;
        case 2:
        case 4: result.add("Carbon dioxide");
            break;
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
            break;
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
            break;
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
            break;
        default:
            break;
    }
    return result;
}
참고: 동일한 코드를 동일한 대기 구성을 가진 행성과 비교했습니다. 그리고 우리는 연속적인 사례 구성을 사용하여 이를 수행했습니다 . 따라서 우리 고향 행성의 대기 구성을 얻으려면 매개변수 3을 사용하여 메서드를 호출합니다.
getPlanetAtmosphere(3).
System.out.println(getPlanetAtmosphere(3)) вернет нам [Углекислый газ, Азот, Кислород].
break로 실험하기 break 문을 모두 제거하면 어떻게 될까요 ? 실제로 시도해 보겠습니다.
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
        case 2:
        case 4: result.add("Carbon dioxide");
        case 3: result.add("Carbon dioxide");
            result.add("Nitrogen");
            result.add("Oxygen");
        case 5:
        case 6: result.add("Hydrogen");
            result.add("Helium");
        case 7:
        case 8: result.add("Methane");
            result.add("Hydrogen");
            result.add("Helium");
        default:
    }
    return result;
}
방법의 결과를 인쇄하면 System.out.println(getPlanetAtmosphere(3))우리 고향 행성은 생명체에 그다지 적합하지 않을 것입니다. 아니면 적합합니까? 스스로 판단하세요: [이산화탄소, 질소, 산소, 수소, 헬륨, 메탄, 수소, 헬륨], 왜 이런 일이 발생했나요? 프로그램은 첫 번째 일치 이후부터 스위치 블록이 끝날 때까지 모든 사례를 실행했습니다.

과도한 최적화 중단

중단 지시문 과 선택 옵션을 다르게 배열하여 방법을 개선할 수 있습니다.
public static List<String> getPlanetAtmosphere(int seqNumberFromSun) {
    List<String> result = new ArrayList<>();
    switch (seqNumberFromSun) {
        case 1: result.add("No Atmosphere");
                break;
        case 3: result.add("Nitrogen");
                result.add("Oxygen");
        case 2:
        case 4: result.add("Carbon dioxide");
                break;
        case 7:
        case 8: result.add("Methane");
        case 5:
        case 6: result.add("Hydrogen");
                result.add("Helium");
    }
     return result;
}
더 짧아보이죠? 사례 순서를 조정 하고 재그룹화하여 전체 진술 수를 줄였습니다. 이제 각 유형의 가스가 단 한 줄의 코드로 목록에 추가됩니다. 방법의 마지막 예 목록은 작업을 보여주기 위한 목적으로만 표시되며 이러한 스타일로 작성하는 것은 권장되지 않습니다 . 유사한 코드의 작성자(그리고 훨씬 더 많은 타사 프로그래머)가 이를 유지해야 한다면 선택 블록 형성을 위한 논리와 Java 스위치 문에 대한 실행 코드를 복원하는 것이 매우 어려울 것입니다.

if와의 차이점

ifswitch 문은 모양이 비슷 하지만 다중 선택 연산자 스위치는 특정 값에 따라 실행 옵션을 선택하는 반면 if에서는 실행 옵션을 선택한다는 점을 잊지 마세요. 모든 논리적 표현이 될 수 있습니다. 코드를 디자인할 때 이 사실을 고려하세요. 다양한 Java 버전의 스위치 혁신을 자세히 살펴보겠습니다.

Java 7에서 전환

Java 7 이전에는 byte, short, char 및 int 기본 형식을 스위치 값으로 사용할 수 있었습니다. 위에 나열된 기본 유형인 Character, Byte, Short 및 Integer의 열거형 및 래퍼도 지원되었습니다. 그러나 종종 우리는 자바 스위치 문자열의 값을 찾아야 합니다! Java 6에서는 다음과 같습니다.
DayOfWeek day = DayOfWeek.fromValue("Thursday");

switch (day) {
  case MONDAY:
     System.out.println("Today is windy !");
     break;
  case THURSDAY:
     System.out.println("Today is sunny !");
     break;
  case WEDNESDAY:
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
그리고 열거형:
public enum DayOfWeek {
  MONDAY("Monday"),
  THURSDAY("Thursday"),
  WEDNESDAY("Wednesday"),
  NOT_FOUND("Not found");

  private final String value;

  DayOfWeek(final String value) {
     this.value = value;
  }

  public static DayOfWeek fromValue(String value) {
     for (final DayOfWeek dayOfWeek : values()) {
        if (dayOfWeek.value.equalsIgnoreCase(value)) {
           return dayOfWeek;
        }
     }
     return NOT_FOUND;
  }
}
그러나 Java 7부터는 String 유형을 스위치 값으로 사용할 수 있습니다.
String day = "Thursday";

switch (day) {
  case "Monday":
     System.out.println("Today is windy !");
     break;
  case "Thursday":
     System.out.println("Today is sunny !");
     break;
  case "Wednesday":
     System.out.println("Today is rainy!");
     break;
  default:
     System.out.println("Oooops, something wrong !");
}
새로운 기능에도 불구하고 enum을 사용하는 접근 방식은 더 유연하며 사용이 권장됩니다. 이 enum을 여러 번 재사용할 수 있습니다.

Java 12에서 전환

Java 12에서는 패턴 일치를 위한 Switch 표현식이 개선되었습니다. 위의 예에서와 같이 Switch를 사용하는 경우 일부 변수의 값을 설정하려면 값을 계산하여 해당 변수에 할당한 다음 break를 사용해야 했습니다.
int count = 2;
int value;
switch (count) {
  case 1:
     value = 12;
     break;
  case 2:
     value = 32;
     break;
  case 3:
     value = 52;
     break;
  default:
     value = 0;
}
하지만 Java 12의 기능 덕분에 이 표현식을 다음과 같이 다시 작성할 수 있습니다.
int value = switch (count) {
  case 1:
     break 12;
  case 2:
     break 32;
  case 3:
     break 52;
  default:
     break 0;
};
변경 사항을 조금 살펴보겠습니다.
  1. 이전에는 케이스 블록 내부에 변수 값을 설정했다면 스위치 문 자체에서는 아무 것도 반환할 수 없었기 때문에 이제 그런 기회가 생겼고, 스위치를 사용하여 직접 값을 반환합니다.

  2. 이전에는 더 이상 break 오른쪽에 아무 것도 가질 수 없었지만 이제는 이를 스위치 값을 반환하는 return 문으로 사용합니다. 콜론 표시는 명령문 블록의 진입점을 표시합니다. 즉, 다른 레이블이 발견되더라도 해당 지점부터 아래의 모든 코드 실행이 시작됩니다.

    그 결과는 마크에서 마크로의 엔드-투-엔드 전환이며, 이를 폴스루( fall -through)라고도 합니다.

Java의 스위치 문 - 2이러한 패스를 완료하려면 모든 요소를 ​​완전히 통과하거나 break 또는 return을 사용해야 합니다. Java 12의 혁신을 통해 람다 연산자를 사용할 수 있는 기능이 제공되어 오른쪽에 있는 코드만 실행됩니다. "실패" 없이. 이 경우 이전 예는 어떻게 보일까요?
int count = 2;
int value = switch (count) {
  case 1 -> 12;
  case 2 -> 32;
  case 3 -> 52;
  default -> 0;
};
코드가 훨씬 단순해졌죠? 그리고 한 가지 더: 람다 연산자는 콜론과 유사한 일반적인 역할을 할 수도 있으며 그 뒤에 몇 가지 연산이 포함된 전체 블록이 있습니다.
int count = 2;
int value = switch (count) {
  case 1 -> {
     //some computational operations...
     break 12;
  }
  case 2 -> {
     //some computational operations...
     break 32;
  }
  case 3 -> {
     //some computational operations...
     break 52;
  }
  default -> {
     //some computational operations...
     break 0;
  }
};
글쎄, 어떤 경우에는 반환 값이 동일하다면 어떻게 될까요? 실제로는 일부 다른 값에 대해 동일한 경우가 있는 것으로 나타났습니다. Java 12의 새로운 기능을 사용하여 이를 단축하는 방법은 다음과 같습니다.
int count = 2;
int value = switch (count) {
  case 1, 3, 5 -> 12;
  case 2, 4, 6 -> 52;
  default -> 0;
};

Java 13에서 전환

Java 13에서는 스위치가 값을 반환하는 방식이 변경되었습니다. Java 12에서 스위치 블록에 대한 반환 역할을 하는 break 뒤에 반환 값을 썼다면 이제 Yi 단어를 사용하여 값을 반환합니다 . 한번 보자:
int value = switch (count) {
  case 1:
     yield 12;
  case 2:
     yield 32;
  case 3:
     yield 52;
  default:
     yield 0;
};
동시에, return을 위해 break를 사용하여 Java 12에서 작성된 코드는 컴파일되지 않습니다(( Java의 Switch 문 - 3Break가 사용되지만 아무것도 반환할 필요가 없는 상황에서는.

  • if 구조로 인해 코드가 복잡해지는 것을 방지하려면 분기가 3개 이상인 경우 Case 문을 사용하세요 .
  • break 호출 을 사용하여 특정 값(케이스 블록)에 해당하는 각 분기의 논리 블록을 종료하는 것을 잊지 마십시오 .
  • 일부 기본 유형 외에도 switch 문은 EnumString 유형을 표현식으로 사용할 수도 있습니다 .
  • 기본 블록을 기억하세요 . 이를 사용하여 계획되지 않은 선택 값을 처리하세요.
  • 성능을 최적화하려면 가장 일반적인 선택 사항이 포함된 코드 분기를 스위치 블록의 시작 부분으로 이동하세요.
  • 케이스 선택 블록 끝의 구분선을 제거하여 "최적화"에 너무 집착하지 마세요 . 이러한 코드는 이해하기 어렵고 결과적으로 개발 중에 유지 관리하기도 어렵습니다.
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION