[java] Java 랩터에서 정수 랩퍼를 전환하는 데 왜 ‘char’케이스가 컴파일되지 않지만 스위치가 바이트를 초과 할 때 컴파일이 가능합니까?

컴파일하지 않습니다 :

void test(Integer x) {
      switch (x) {
          case 'a':
      }
}

컴파일 OK :

void test(Byte x) {
      switch(x) {
          case 'a':
      }
}



답변

그 이유는 다소 복잡하지만 Java 언어 사양 의 세부 사항 ( 원하는 경우 미세 인쇄 )에 모두 있습니다.

우선, JLS 14.11 은 다음과 같은 switch진술 에 대해 말합니다 .

“스위치 명령문과 연관된 모든 상수는 스위치 명령문의 표현식 유형 ( §5.2 ) 과 호환 가능한 지정이어야합니다 .”

즉 , 각각에 'a'할당 할 수 있어야합니다 .IntegerByte

그러나 그것은 제대로 들리지 않습니다.

  • 왜냐하면 -> 할당이 합법적 이므로 할당 가능 'a' 해야 한다고 생각할 것 입니다 . (모든 값은에 맞습니다 .)Integercharintcharint

  • -> 할당이 합법적이지 않기 때문에 할당 할 'a' 없다고 생각할 것 입니다 . (대부분의 값은 바이트에 맞지 않습니다.)Bytecharbytechar

실제로, 이들 중 어느 것도 맞지 않습니다. 이유를 이해하려면 할당 컨텍스트에서 허용되는 내용에 대한 JLS 5.2 내용을 읽어야 합니다.

“할당 컨텍스트를 사용 하면 다음 중 하나를 사용할 수 있습니다 .

  • 신원 전환 (§5.1.1)
  • 확대 원시 변환 (§5.1.2)
  • 확대 참조 변환 (§5.1.5)
  • 확장 참조 변환 후 언 박싱 변환
  • 확장 참조 변환, 언 박싱 변환, 확장 기본 변환
  • 권투 변환 (§5.1.7)
  • 복싱 변환 후 확장 참조 변환
  • 언 박스 변환 (§5.1.8)
  • 언 박싱 전환 후 확장 원시 전환이 뒤따 랐습니다. “

에서 'a'로 이동하려면 값을 1로 확장 한 다음 상자 를로 확장 Integer해야 합니다 . 그러나 허용되는 전환 조합을 살펴보면 확장 기본 전환 후 복싱 전환을 수행 할 수 없습니다.charintintInteger

따라서 'a'Integer수 없습니다. 첫 번째 경우의 컴파일 오류에 대해 설명합니다.

당신은 생각 'a'Byte허용되는 모든의 목록에없는 원시적 축소 변환을 … 포함하기 때문. 실제로 리터럴은 특별한 경우입니다. JLS 5.2 는 다음과 같이 말합니다.

“또한 표현식이 byte, short, char 또는 int 유형 의 상수 표현식 ( §15.28 ) 인 경우 :

  • 변수가 byte, short 또는 char 유형이고 상수 표현식의 값이 변수 유형으로 표시되는 경우 축소 기본 변환이 사용될 수 있습니다.

  • 변수의 유형 ByteShort,, 또는 Character이고 상수 표현식의 값이 각각 바이트, 짧은 또는 문자로 표시 될 수있는 경우 축소 기본 변환과 복싱 변환이 사용될 수 있습니다 . “

이들의 두 번째 적용 'a'으로 Byte, 때문에 :

  • 문자 리터럴은 상수 표현식이며
  • 의 값 'a'9710 진수이며 byte( -128~ +127) 범위 내에 있습니다.

이것은 두 번째 예에서 컴파일 오류가없는 이유를 설명합니다.


1 – 우리는 상자 수 없습니다 'a'A를 Character한 후 확대 CharacterInteger있기 때문에 Character의 자바 하위하지 않습니다 Integer. 소스 유형이 대상 유형의 하위 유형 인 경우 확대 참조 변환 만 사용할 수 있습니다.


답변