[java] Java 스위치 내에서 변수 선언 및 초기화

Java 스위치에 대해 미친 질문이 있습니다.

int key = 2;

switch (key) {
    case 1:
        int value = 1;
        break;
    case 2:
        value = 2;
        System.out.println(value);
        break;
    default:
        break;
}

시나리오 1- key값이 2이면 성공적으로 값을 2로 인쇄합니다.

시나리오 2-주석 value = 2case 2:달면 The local variable value may be initialized .

질문 :

시나리오 1 : 실행 흐름이 이동하지 않는 경우 case 1:합니다 (시 key = 2), 다음 어떻게 같은 값 변수의 유형을 알 수 있습니까 int?

시나리오 2 : 컴파일러가 값 변수의 유형을으로 알고 있으면 . (선언 및 초기화) intint value = 1;표현식에 액세스해야합니다 case 1:. 그럼 왜 그것이 내가 언급을하겠습니다 때 sqawrk 수행 value = 2case 2:속담, 초기화되지 않았을 수 지역 변수의 값을 .



답변

Switch 문은 기본적으로 범위 지정 측면에서 이상합니다. 에서 JLS의 섹션 6.3 :

블록 (§14.4)에서 지역 변수 선언의 범위는 선언이 나타나는 나머지 블록으로, 자체 이니셜 라이저로 시작하고 지역 변수 선언문의 오른쪽에있는 추가 선언자를 포함합니다.

귀하의 경우, case 2는 실행되지 않더라도 동일한 블록에 있으며 case 1그 뒤에 나타납니다 case 1. 따라서 논리적으로 선언을 “실행”하지 않더라도 지역 변수가 범위 내에 있고 수 있습니다 . (초기화가 가능하지만 선언은 실제로 “실행 가능”하지 않습니다.)

주석 처리하면 value = 2;할당 하면 컴파일러는 여전히 참조하는 변수를 알고 있지만 값을 할당하는 실행 경로를 거치지 않았기 때문에 시도 할 때와 같은 오류가 발생합니다. 명확하게 할당되지 않은 다른 지역 변수를 읽습니다.

다른 경우에 선언 된 지역 변수를 사용 하지 않는 것이 좋습니다 . 지금까지 본 것처럼 코드를 매우 혼란스럽게 만듭니다. switch 문에 지역 변수를 도입 할 때 (드물게 시도하는 경우-사례가 매우 짧아야합니다. 이상적으로는) 일반적으로 새로운 범위를 도입하는 것을 선호합니다.

case 1: {
    int value = 1;
    ...
    break;
}
case 2: {
    int value = 2;
    ...
    break;
}

나는 이것이 더 명확하다고 믿습니다.


답변

변수가 선언되었지만 (int로) 초기화되지 않았습니다 (초기 값이 할당 됨). 라인을 생각해보십시오.

int value = 1;

같이:

int value;
value = 1;

int value부분은 컴파일 타임에 int 인 value라는 변수가 있음을 컴파일러에 알립니다. value = 1부분을 초기화하지만 실행 시간에 발생, 스위치의 해당 분기를 입력하지 않으면 전혀 발생하지 않습니다.


답변

에서 http://www.coderanch.com/t/447381/java-programmer-SCJP/certification/variable-initialization-within-case-block

선언은 컴파일 타임에 처리되며 코드의 실행 흐름에 의존하지 않습니다. value스위치 블록의 로컬 범위 내에서 선언 되기 때문에 선언 지점부터 해당 블록의 모든 위치에서 사용할 수 있습니다.


답변

JEP 325 : JDK-12 얼리 액세스 빌드의 Switch Expressions (미리보기) 통합으로 . 에서 볼 수있는 특정 변화가 존의 대답은

  1. 로컬 변수 범위 -스위치 케이스의 로컬 변수는 이제 전체 스위치 블록 대신 케이스 자체에 로컬이 될 수 있습니다. Day추가 설명을 위해 enum 클래스를고려한 예 (Jon이 구문 론적으로 시도한 것과 유사):

    public enum Day {
        MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
    }
    
    // some another method implementation
    Day day = Day.valueOf(scanner.next());
    switch (day) {
        case MONDAY,TUESDAY -> {
            var temp = "mon-tue";
            System.out.println(temp);
        }
        case WEDNESDAY,THURSDAY -> {
            var temp = Date.from(Instant.now()); // same variable name 'temp'
            System.out.println(temp);
        }
        default ->{
            var temp = 0.04; // different types as well (not mandatory ofcourse)
            System.out.println(temp);
        }
    }
  2. Switch Expressions- 의도가 변수에 값을 할당 한 다음 사용하려는 경우 스위치 표현식을 사용할 수 있습니다. 예 :

    private static void useSwitchExpression() {
        int key = 2;
        int value = switch (key) {
            case 1 ->  1;
            case 2 -> 2;
            default -> {break 0;}
        };
        System.out.println("value = " + value); // prints 'value = 2'
    }


답변

이 설명이 도움이 될 수 있습니다.

    int id=1;

    switch(id){
        default:
            boolean b= false; // all switch scope going down, because there is no scope tag

        case 1:
            b = false;
        case 2:{
            //String b= "test"; you can't declare scope here. because it's in the scope @top
            b=true; // b is still accessible
        }
        case 3:{
            boolean c= true; // case c scope only
            b=true; // case 3 scope is whole switch
        }
        case 4:{
            boolean c= false; // case 4 scope only
        }
    }


답변

자바 사양 :

https://docs.oracle.com/javase/specs/jls/se12/html/jls-14.html#jls-14.11

레이블이있는 중단으로 인한 갑작스러운 완료의 경우 레이블이있는 문에 대한 일반 규칙 (§14.7)에 의해 처리됩니다.

https://docs.oracle.com/javase/specs/jls/se12/html/jls-14.html#jls-14.7

라벨이있는 진술 :

LabeledStatement : 식별자 : 문

LabeledStatementNoShortIf : 식별자 : StatementNoShortIf

C 및 C ++와 달리 Java 프로그래밍 언어에는 goto 문이 없습니다. 식별자 문 레이블은 레이블이있는 문 내 어디에서나 나타나는 break (§14.15) 또는 continue (§14.16) 문과 함께 사용됩니다.

레이블이있는 명령문의 레이블 범위는 즉시 포함 된 명령문입니다.

즉, case 1, case 2는 switch 문 내의 레이블입니다. break 및 continue 문을 레이블에 적용 할 수 있습니다.

레이블은 문의 범위를 공유하므로 레이블 내에 정의 된 모든 변수는 switch 문의 범위를 공유합니다.


답변