2014-03-06 3 views
2

두 자리 숫자를 2000 + 숫자로 변환하는 메서드를 작성하려고 시도하고 있으며 다른 모든 숫자를 그대로 반환하며 null이 인수로 전달되면 null을 반환합니다.NullPointerException의 출처는 어디입니까?

이 구현 의도

private Integer convertTo4Digits(Integer modelYear) { 
    boolean isTwoDigit = modelYear != null && modelYear < 100; 
    if (isTwoDigit) { 
     return 2000 + modelYear; 
    } else { 
     return modelYear; 
    } 
} 

로 작동하지만 NULL로 호출 할 때이 사람은 return 문에서 NPE와 함께 실패합니다.

private Integer convertTo4Digits(Integer modelYear) { 
    return (modelYear != null && modelYear < 100) ? (2000 + modelYear) : modelYear; 
} 

또는이 버그입니까? 나는 (정수에 명시 적 캐스트를 참고) JDK와 1.7.0_04

+0

"왜 삼항 연산자가 NullPointerException을 발생 시키는가?"로 질문을 변경해야합니다. –

답변

3

는 I는 두 번째와 세 번째 피연산자 중 하나는 원시 타입 T 인 경우 응답이 chapter 15.25 of the JLS

에서 발견 될 수 있다고 생각하고, 다른 유형은 복싱 변환 (§5.1을 적용한 결과이다. 7)을 T로하면 조건식의 유형은 T입니다.

따라서 두 번째 피연산자 또는 세 번째 피연산자 중 하나가 원시 유형 인 경우 표현식의 유형은 프리미티브입니다. 따라서 null 참조를 전달하면 : modelYear 지점이 실행됩니다. 그러나 하나의 피연산자가 원시적이기 때문에 그것은 언 박싱되어야합니다. 이로 인해 NPE가 발생합니다.

당신이 Integer

(modelYear != null && modelYear < 100) ? (Integer) (2000 + modelYear) : modelYear; 

때문에에 두 번째 피연산자를 캐스팅하고 있기 때문에 당신의 자신의 대답이 문제를 해결

private convertTo4Digits(Ljava/lang/Integer;)Ljava/lang/Integer; 
L0 
    LINENUMBER 46 L0 
    ALOAD 1 
    IFNULL L1 
    ALOAD 1 
    INVOKEVIRTUAL java/lang/Integer.intValue()I 
    BIPUSH 100 
    IF_ICMPGE L1 
    SIPUSH 2000 
    ALOAD 1 
    INVOKEVIRTUAL java/lang/Integer.intValue()I 
    IADD 
    GOTO L2 
L1 
    LINENUMBER 47 L1 
    ALOAD 1 
    INVOKEVIRTUAL java/lang/Integer.intValue()I 
L2 
    LINENUMBER 46 L2 
    INVOKESTATIC java/lang/Integer.valueOf(I)Ljava/lang/Integer; 
    ARETURN 

생성 된 바이트 코드를 살펴 경우, 당신은이를 볼 수 있습니다 두 번째 피연산자와 네 번째 피연산자는 모두 원시 유형이 아닙니다. 따라서 위에서 게시 한 JLS 규칙이 적용되지 않으며 NPE가 사라졌습니다.

0

오 이놈을 이클립스 Keple을이 하나의 작품을 사용하고 있습니다 :

(modelYear != null && modelYear < 100) ? (Integer) (2000 + modelYear) : modelYear; 

이 문제가된다 삼항 연산자의 첫 번째 지점이 결정 연산자의 결과 유형 : 질문 버전의 int

이제 modelYear (null)은 boxed되기 전에 NPE를 오른쪽으로 만드는 unboxed가됩니다.

관련 문제