[Java] long 에서 int "안전하게" 형변환 / 타입 캐스팅

2022. 12. 17. 10:10Backend/☕️ Java

 

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() 메서드를 사용하는 것을 권장한다.