스위치에서 null을 사용하는 방법


202
Integer i = ...

switch (i){
    case null:
        doSomething0();
        break;    
    }

위의 코드에서 switch case 문에 null을 사용할 수 없습니다. 어떻게 다르게 할 수 있습니까? default다른 것을하고 싶기 때문에 사용할 수 없습니다 .


9
널 조건이있는 경우 (I == NULL) 용 스위치 검사 전에 {//는 해봐요}
Nagaraju Badaeni

8
이것은 실제로 스위치를 유용하게 만듭니다. 다른 패턴 일치 언어는이 방식으로 작동합니다.
Pyrolistical 2016 년

답변:


276

switchJava 의 명령문에서는 불가능합니다 . 확인하기 null전에 switch:

if (i == null) {
    doSomething0();
} else {
    switch (i) {
    case 1:
        // ...
        break;
    }
}

switch명령문 *에 임의의 객체를 사용할 수 없습니다 . 컴파일러가 switch (i)어디에 있는지 i에 대해 불만을 제기하지 않는 이유 Integer는 Java가에서 Integerto를 자동으로 개봉하기 때문 int입니다. assylias가 이미 말했듯이, unboxing은 NullPointerException때 를 던질 것 i입니다 null.

* Java 7부터 명령문 String에서 사용할 수 있습니다 switch.

Oracle Docs-Switch의 자세한 내용 switch(널 변수가 포함 된 예 포함)


16
switch 문에 열거 형을 사용할 수도 있습니다.
joriki

27
unboxing 때문에 null Integer 또는 다른 Wrapper 클래스를 사용할 수 없습니다. 그러나 열거 형과 문자열은 어떻습니까? 왜 널이 될 수 없습니까?
루안 니코

9
null 단락이 "기본"사례에 매핑되거나 null 스위치에 대한 특수 사례가 문자열에 대해 구현되지 않은 이유를 이해하지 못합니다. 항상 null 검사를 수행해야하므로 스위치를 사용하여 코드를 무의미하게 단순화합니다. 나는 단순화가 스위치의 유일한 사용이라고 말하지는 않습니다.
Reimius

3
@Reimius는 항상 null 검사를 수행 할 필요는 없습니다. 메소드에 제공 한 코드 계약을 존중한다면 거의 항상 널 검사로 코드가 복잡해 지지 않도록 관리 할 수 ​​있습니다 . 그러나 어설 션을 사용하는 것이 항상 좋습니다.
Joffrey

@LuanNico의 쿼리에 대한 답변을 알고 싶습니다. null작업 Stringenum유형 작업시 유효한 사례가 될 수없는 것은 비합리적인 것 같습니다 . 아마도 enum구현은 ordinal()장면 뒤의 호출에 의존 하지만 (그렇더라도 null-1의 '정수'를 가진 것으로 취급하지 않는 이유 String는 무엇 입니까?), 버전은 사용 intern()하고 포인터 비교를 수행합니다 (또는 그렇지 않으면 목적)?
aroth


40

switch(i)내가 경우 NullPointerException이 발생합니다 null가를 언 박싱하려고하기 때문에, Integerint. 따라서 case null불법적 인 것은 어쨌든 결코 도달하지 못했을 것입니다.

switch명령문 앞에 i가 널이 아닌지 확인해야 합니다.


23

Java 문서는 분명히 다음과 같이 말했습니다.

스위치 레이블로 null을 사용하는 것을 금지하면 실행할 수없는 코드를 작성할 수 없습니다. 스위치식이 박스형 기본 형식 또는 열거 형과 같은 참조 형식 인 경우식이 런타임에서 null로 평가되면 런타임 오류가 발생합니다.

Swithch 문을 실행하기 전에 null을 확인해야합니다.

if (i == null)

스위치 문을 참조하십시오

case null: // will never be executed, therefore disallowed.

1
링크의 javadoc은 더 이상 "스위치 레이블로 널 (null)을 사용하지 못하도록 금지 [etc.]]라고 표시하지 않습니다.
Patrick M


14

주어진:

public enum PersonType {
    COOL_GUY(1),
    JERK(2);

    private final int typeId;
    private PersonType(int typeId) {
        this.typeId = typeId;
    }

    public final int getTypeId() {
        return typeId;
    }

    public static PersonType findByTypeId(int typeId) {
        for (PersonType type : values()) {
            if (type.typeId == typeId) {
                return type;
            }
        }
        return null;
    }
}

나에게 이것은 일반적으로 데이터베이스의 조회 테이블과 거의 일치하지 않습니다 (드물게 업데이트되는 테이블의 경우에만).

그러나 findByTypeIdswitch 문에서 사용하려고 할 때 (보통 사용자 입력에서) ...

int userInput = 3;
PersonType personType = PersonType.findByTypeId(userInput);
switch(personType) {
case COOL_GUY:
    // Do things only a cool guy would do.
    break;
case JERK:
    // Push back. Don't enable him.
    break;
default:
    // I don't know or care what to do with this mess.
}

... 다른 사람들이 말했듯이 이것은 NPE @ switch(personType) {입니다. 구현을 시작한 한 가지 해결 방법 (예 : "솔루션")은 UNKNOWN(-1)유형 을 추가하는 것이 었습니다 .

public enum PersonType {
    UNKNOWN(-1),
    COOL_GUY(1),
    JERK(2);
    ...
    public static PersonType findByTypeId(int id) {
        ...
        return UNKNOWN;
    }
}

이제는 계산되는 위치에서 널 검사를 수행 할 필요가 없으며 UNKNOWN유형을 처리할지 여부를 선택할 수 있습니다 . (참고 : -1비즈니스 시나리오에서는 가능성이 높지 않지만 사용 사례에 적합한 것을 선택하십시오).


2
UNKNOWN내가 본 적이 있고 nullchecks를 극복하는 가장 좋은 솔루션입니다.
membersound

5

당신은

if (i == null) {
   doSomething0();
} else {
   switch (i) {
   }
}

4

일부 라이브러리는 내장 Java switch문 에 대한 대안을 제공하려고 합니다. Vavr 은 그중 하나이며 패턴 일치로 일반화합니다.

다음은 해당 문서 의 예입니다 .

String s = Match(i).of(
    Case($(1), "one"),
    Case($(2), "two"),
    Case($(), "?")
);

모든 술어를 사용할 수 있지만 많은 술어를 즉시 제공하며 $(null)완벽하게 합법적입니다. 나는 이것이 대안보다 더 우아한 해결책을 찾았지만, 이것은 java8과 vavr 라이브러리에 대한 의존성이 필요합니다 ...



2
switch (String.valueOf(value)){
    case "null":
    default: 
}

0

당신은 할 수 없습니다. 스위치에서 기본 요소 (int, char, short, byte) 및 String (Java 7의 문자열 만)을 사용할 수 있습니다. 프리미티브는 null 일 수 없습니다. 전환하기 전에 별도의 상태를
확인하십시오 i.


4
열거 형도 사용할 수 있습니다.
Karu

5
열거 형이 null 인 경우 동일한 문제가 발생합니다. 이 기본 조항이 있기 때문에 BTW, 그것은 스위치가 null을 처리 할 수없는 매우 이상하다

1
@LeonardoKenji Default 절은 실제로 null과 관련이 없습니다. 스위치를 켜면 다른 경우를 확인하기 위해 역 참조되므로 기본 절은 null 경우를 처리하지 않습니다 (NullPointerException이 발생하기 전에 발생합니다).
Ben

2
필자는 기본 조항이 이전 사례에서 파악하지 못한 다른 가능한 열거 형 값으로 null을 처리해야한다고 생각했다고 생각합니다.
Leo

0

SWITCH 작동 방식을 고려하십시오.

  • 프리미티브의 경우 자동 권투에 대해 NPE로 실패 할 수 있음을 알고 있습니다.
  • 그러나 String 또는 enum의 경우 equals 메소드를 호출 할 수 있으며, equals가 호출되는 LHS 값이 분명히 필요합니다. 따라서 null에서 호출 할 수있는 메서드가 없으면 switch 는 null을 처리 할 수 없습니다 .

0

@tetsuo 답변을 기반으로 java 8 :

Integer i = ...

switch (Optional.ofNullable(i).orElse(DEFAULT_VALUE)) {
    case DEFAULT_VALUE:
        doDefault();
        break;    
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.