[Java] long 에서 int "안전하게" 형변환 / 타입 캐스팅
1. primitive type long -> int
당연한 얘기지만 원시형 long 타입은 intValue() 메서드를 사용할 수 없다. 원시형은 메모리 주소에 저장된 '값 자체' 만 가질 뿐, 그 외의 메서드 등은 가지지 못하기 때문이다.
때문에 primitive type 인 long 을 int 형으로 변환하려면, Long.valueOf() 메서드로 우선 감싸줘야 한다.
Long.valueOf() 메서드 내부는 아래와 같다.
원시형 l 변수를 new Long() 의 인자로 넣어 참조형으로 리턴한다.
2. long 에선 8 바이트인 내가, int 에선 4 바이트?.?
int 는 4 바이트, long 은 8 바이트를 메모리로부터 할당받는다.
즉 int 는 -2,147,483,648 ~ 2,147,483,647 범위의 숫자를 저장할 수 있고,
long 은 그보다 큰 범위(-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807) 까지 저장할 수 있다.
즉 어떤 long 타입의 변수 값이 2,147,483,648 일 때, 해당 변수를 int 로 변환하면 어떻게 될까?
int 형 2,147,483,648 이 아닌 overflow 된 값이 출력된다. 우리가 원하지 않는 값이 출력되는 것을 알 수 있다.
3. Throw ArithmeticException
그렇다면 2,147,483,648L 처럼 정수범위를 초과하는 값을 int 형으로 변경하려면 어떻게 해야하나?
우선 이 질문은 잘못됐다. 정수형에게 주어진 범위가 있는데, 그 범위를 넘은 값을 정수로 변환하고 싶다? 앞뒤가 맞지 않다.
제대로 된 질문은 long 타입을 int 로 안전하게 변환하는 방법
은 무엇인가 이다.
long 타입을 int 로 형변환 할 때, overflow 가 발생하면 ArithmeticException 예외
를 던지는 Math.toIntExact() 메서드를 사용할 수 있다.
toIntExact() 메서드 내부는 아래와 같다.
long 타입 변수를 int 로 캐스팅할 때, 값이 다르면 ArithmeticException 을 던진다.
두 값이 서로 같으면, int 로 캐스팅하여 리턴한다.
결론
long 타입을 int 로 형변환 할 때는 overflow 를 방지할 수 있는 Math.toIntExact() 메서드를 사용하는 것을 권장한다.