값을 할당 할 때 이상한 Java 3 진 동작. 이 일이 발생하기 위해 Java가 무대 뒤에서 무엇을하고 있습니까?


10

며칠 전, Java가 어떻게 또는 왜 다음을 수행 할 수 있는지에 대한 문서를 찾을 수없는 매혹적인 시나리오를 만났습니다. 이 스 니펫은 단순한 버그 형태입니다.

    @Test
    public void test() {
      boolean bool = false;
      Integer intVal = Integer.valueOf(5);
      Long longVal = null;
      Long result = bool ? intVal : longVal;

      System.out.println(" > " + result);
   }

위의 스 니펫에서 :

bool = true이면 '5'값을 얻습니다.

그러나 bool = false이면 삼항 연산을 평가하려고 할 때 널 포인터 예외가 발생합니다. 인쇄 문이 아닙니다.


이 문제를 해결하려면 'result'를 다음과 같이 변경하십시오.

Long result = bool ? Long.valueOf(intVal) : longVal;

이렇게하면 내가 필요한 예상 동작이 나타납니다.

bool = true이면 '5'값을 얻습니다.

그러나 bool = false이면 'null'이됩니다.


이제 재미있는 부분은 이것을 일반적인 if / else 문으로 나누면 java가 컴파일 할 수 없다는 것입니다

longVal = intVal; 

그러나 삼항 연산자를 통해 그것을 포착하지 못합니다. 그렇다면 Java는 원래 스 니펫에서 널 포인트로 만들기 위해 무엇을하고 있습니까?

(자바 11)

답변:


10

이렇게하면 :

Long result = bool ? intVal : longVal

이 표현식은 a를 반환 long하고, boolfalse null이면 result변수 에 맞게 Long 값으로 unboxe 를 시도 하고 NPE를 발생시킵니다.

이렇게하면 :

Long result = bool ? Long.valueOf(intVal) : longVal

이 표현식은 이미 반환 된 상태 Long이므로 개봉 할 필요가 없으며 null값이 result변수에 성공적으로 할당됩니다 .

참고:

주석 섹션에서 논의 된 바와 같이, 이것이 발생하는 이유를 더 잘 이해하려면 JLS의 다음 섹션을 확인하십시오.


Integer / Long이 bnp (Integer, Long)를 초래한다는 것이 "명확한" 다른 참조 표 15.25 A에서 E에 놀랐습니다 .
매트

좋은 대답입니다. 일반적으로 내부에 무슨 일이 일어나고 있는지 전혀 모를 때 컴파일 된 바이트 코드를 살펴 보는 것이 좋습니다. 최소한 최소한의 코드 스 니펫을 추출 할 때 훈련의 문제, 그것을 읽고 이해하는 방법에 관한 것입니다.
Jan은

애즈 JLS 섹션 5.6.2 말한다 : "어떤 피연산자 참조 형의 경우는 언 박싱 변환 처리"; "소박한 원시적 변환 (§5.1.2)이 적용됨 [..]"
Diego Magdaleno
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.