3항 연산자 버그

버그라고 불러야 할지 놓칠 수 있는 부분이라 해야할지 애매하다. 정말 간단한 예제를 보면서 어떤 특징을 지니고 있는 살펴보자

아래의 두 코드의 차이점을 알고 어떤 예외가 일어날지 알고 있다면 이 포스팅은 볼 필요가 없다.

Number n1 = null;
Integer n1 = null;
Number m = (2/2==1)? n1 : 0;

위의 두개의 코드를 돌려보면 위의 코드는 정상, 아래의 코드에서는 NPE가 뜬다. 갑자기 뜬끔없이 널포인트가 왜 뜨는걸까??

자 다시 아래의 코드를 돌려보도록 하자

Integer n1 = null;
Number m = (2/2==1)? n1 : Integer.valueOf(0);

이번에는 정상적으로 코드가 돌아가는 것을 확인할 수 있다.

눈치가 빠른 사람들은 autoBoxing이 관여되어 있다는 것을 금세 알아차릴 것이다.

일단 정답부터 말하자면 3항 연산자는 앞에 선언된 수신 변수를 기반으로 데이터를 저장하지 않고 뒤의 두개의 표현식들의 공통 타입을 리턴값으로 한다.

표현식 1의 타입은 Integer, 표현식2의 타입은 int 이라서 두개의 공통 타입은 int이다. 따라서 컴파일러는 3항연산자의 최초 리턴 타입을 int로 잡아놓은 후에 Number로 캐스팅 한다는 뜻이다.

int m = (2/2==1)? n1 : 0; // Integer인 n1이 리턴이 되고 unboxing 하기 위해 valueOf()가 호출
Number n = m

그래서 에러가 났었던 코드를 보면 조건문에 의해서 최초 Integer 타입이 리턴이 되었을테고, 이 Integer를 int로 만들기 위해 Integer.valueOf(null) 을 호출했기에 에러가 난 것이다