Java 7 switch
문이 null
케이스를 지원하지 않고 대신 던지는 이유가 궁금합니다 NullPointerException
. 아래의 주석 처리 된 줄을 참조하십시오 ( 의 Java 자습서 기사에서switch
가져온 예제 ).
{
String month = null;
switch (month) {
case "january":
monthNumber = 1;
break;
case "february":
monthNumber = 2;
break;
case "march":
monthNumber = 3;
break;
//case null:
default:
monthNumber = 0;
break;
}
return monthNumber;
}
이것은 if
매번 switch
사용 하기 전에 널 체크에 대한 조건을 피했을 것 입니다.
답변
damryfbfnetsi으로 종료 지점 코멘트에, JLS §14.11는 다음과 같은 메모를 가지고 :
null
스위치 레이블로 사용하는 것을 금지하는 것은 실행할 수없는 코드를 작성하는 것을 방지합니다. 상기 중간switch
표현은 참조 형식,이다String
또는 박스형 원시 형 또는 열거 형 다음 런타임 에러 발현 평가되는 경우에 발생한다null
런타임. Java 프로그래밍 언어 설계자의 판단에 따르면 전체switch
명령문을 조용히 건너 뛰 거나default
레이블 (있는 경우 ) 뒤에 명령문 (있는 경우)을 실행하도록 선택 하는 것보다 더 나은 결과 입니다.
(강조 광산)
마지막 문장은를 사용할 가능성을 건너 뛰지 만 case null:
합리적으로 보이며 언어 디자이너의 의도에 대한 견해를 제공합니다.
구현 세부 사항을 살펴보면 Christian Hujer 의이 블로그 게시물null
에 스위치에서 허용되지 않는 이유 에 대한 통찰력있는 추측 이 있습니다 ( enum
스위치가 아닌 스위치에 중점을두고 있음 String
).
내부적
switch
으로이 문은 일반적으로 tablesswitch 바이트 코드로 컴파일됩니다. 그리고switch
그 사건뿐만 아니라 “물리적”주장 은int
s입니다. 스위치를 켤 int 값은 메서드를 호출하여 결정됩니다Enum.ordinal()
. […] 서수는 0에서 시작합니다.즉, 매핑
null
하는0
것은 좋은 생각이 아닙니다. 첫 번째 열거 형 값의 스위치는 null과 구별 할 수 없습니다. 1에서 열거 형의 서수를 세는 것이 좋은 생각이었을 것입니다. 그러나 그렇게 정의되지 않았고이 정의는 변경할 수 없습니다.
반면 String
스위치 다르게 구현되어 상기 enum
스위치는 첫 번째 들어오는 기준 인 경우에 동작한다 참조 형식에 스위칭 방법에 대한 선례 null
.
답변
일반적으로 null
다루기 힘들다. 더 나은 언어는 null
.
귀하의 문제는
switch(month==null?"":month)
{
...
//case "":
default:
monthNumber = 0;
}
답변
예쁘지는 않지만 String.valueOf()
스위치에서 null String을 사용할 수 있습니다. 을 찾으면 null
로 변환하고 "null"
, 그렇지 않으면 전달한 것과 동일한 문자열을 반환합니다. "null"
명시 적으로 처리하지 않으면 default
. 유일한주의 사항은 문자열 "null"
과 실제 null
변수 를 구분할 방법이 없다는 것입니다 .
String month = null;
switch (String.valueOf(month)) {
case "january":
monthNumber = 1;
break;
case "february":
monthNumber = 2;
break;
case "march":
monthNumber = 3;
break;
case "null":
monthNumber = -1;
break;
default:
monthNumber = 0;
break;
}
return monthNumber;
답변
이것은 왜 던지는 지 대답하려는 시도입니다. NullPointerException
아래의 javap 명령의 출력은 인수 문자열 case
의 해시 코드를 기반으로 선택한 것을 나타내 switch
므로 .hashCode()
null 문자열 에서이 호출 될 때 NPE를 발생 시킵니다.
6: invokevirtual #18 // Method java/lang/String.hashCode:()I
9: lookupswitch { // 3
-1826660246: 44
-263893086: 56
103666243: 68
default: 95
}
이것은 Java의 hashCode가 다른 문자열에 대해 동일한 값을 생성 할 수 있습니까? 에 대한 답변을 기반으로 함을 의미합니다 . , 드물기는하지만 여전히 두 개의 케이스가 일치 할 가능성이 있습니다 (동일한 해시 코드를 가진 두 개의 문자열) 아래이 예를 참조하십시오.
int monthNumber;
String month = args[0];
switch (month) {
case "Ea":
monthNumber = 1;
break;
case "FB":
monthNumber = 2;
break;
// case null:
default:
monthNumber = 0;
break;
}
System.out.println(monthNumber);
어느 Javap
10: lookupswitch { // 1
2236: 28
default: 59
}
28: aload_3
29: ldc #22 // String Ea
31: invokevirtual #24 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
34: ifne 49
37: aload_3
38: ldc #28 // String FB
40: invokevirtual #24 // Method java/lang/String.equals:(Ljava/lang/Object;)Z
43: ifne 54
46: goto 59 //Default
당신은 단지 하나의 사건이 생성됩니다 볼 수 있듯이을 위해 "Ea"
하고 "FB"
있지만, 두 가지로 if
조건이 각각의 경우 문자열 일치를 확인합니다. 이 기능을 구현하는 매우 흥미롭고 복잡한 방법!
답변
긴 이야기 짧게 … (그리고 충분히 흥미 로웠기를 바랍니다 !!!)
Enum은 Java1.5 ( 2004 년 9 월 ) 에서 처음 도입되었으며 String 켜기 를 허용 하라는 버그 가 오랫동안 제기되었습니다 ( 95 년 10 월 ). 2004 년 6 월에 해당 버그에 게시 된 댓글을 보면이 버그를 연기 ( 무시 )하고 결국 0부터 시작하는 서수로 ‘열거 형’을 도입하고 결정한 같은 해에 Java 1.5를 출시 한 것 같습니다 ( missed ) 열거 형에 대해 null을 지원하지 않습니다. 나중에 Java1.7 ( 2011 년 7 월 )에서 그들은 따랐습니다 ( 강제Don't hold your breath. Nothing resembling this is in our plans.
) String과 동일한 철학 (즉, 바이트 코드를 생성하는 동안 hashcode () 메서드를 호출하기 전에 null 검사가 수행되지 않음).
따라서 enum이 처음에 들어오고 서수 시작이 0으로 구현되어 스위치 블록에서 null 값을 지원할 수 없었고 나중에 String으로 동일한 철학을 강요하기로 결정했습니다. 스위치 블록에서 허용됩니다.
TL; DR String을 사용하면 Java 코드를 바이트 코드로 변환하는 동안 NPE (null에 대한 해시 코드를 생성하려는 시도로 인해 발생)를 처리 할 수 있었지만 결국 그렇게하지 않기로 결정했습니다.
참조 :
TheBUG ,
JavaVersionHistory ,
JavaCodeToByteCode ,
SO
답변
Java Docs에 따르면 :
스위치는 byte, short, char 및 int 기본 데이터 유형과 함께 작동합니다. 또한 열거 형 (Enum Types에서 설명), String 클래스, 그리고 Character, Byte, Short 및 Integer (Numbers 및 Strings에서 설명)와 같은 특정 기본 유형을 래핑하는 몇 가지 특수 클래스와 함께 작동합니다.
때문에 null
어떤 유형이없고, 아무것도의 인스턴스가 아닌, 그것을 switch 문 작동하지 않습니다.
답변
대답은 단순히 참조 유형 (예 : boxed primitive 유형)과 함께 스위치를 사용하는 경우 unboxing이 NPE를 던지기 때문에 표현식이 null이면 런타임 오류가 발생한다는 것입니다.
그래서 케이스 null (불법)은 어쨌든 실행될 수 없습니다.)