HOWTO · Java
Java에서 `long`과 `int` 데이터 타입의 차이
이 기사에서는 Java에서 long 및 int 데이터 유형의 차이점을 설명합니다.
이 페이지의 내용
프로그램에서 예상하는 값이 int의 범위에 들어오면 int를 사용하고, 더 큰 값이 될 수 있으면 long을 선택하세요. 둘 다 부호 있는 원시 정수 타입입니다. 래퍼 클래스인 Integer와 Long은 참조 타입을 사용하는 API와 컬렉션에 쓰이는 객체입니다. 아래에서는 두 타입의 범위와 리터럴 표기법, 래퍼가 유용한 경우를 비교합니다.
Java에서 int와 long 중 선택하기
int는 32비트이며 -2,147,483,648부터 2,147,483,647까지의 값을 나타냅니다. long은 64비트이며 -9,223,372,036,854,775,808부터 9,223,372,036,854,775,807까지의 값을 나타냅니다. 데이터가 가질 것으로 예상되는 범위에 따라 선택하세요. 타입 이름만으로 모든 산술 연산의 결과가 범위 안에 든다고 보장되지는 않습니다.
| 타입 | 너비 | 최솟값 | 최댓값 |
|---|---|---|---|
int |
32비트 | -2,147,483,648 | 2,147,483,647 |
long |
64비트 | -9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
접미사가 없는 10진 정수 리터럴은 값이 범위에 들어오면 일반적으로 int 타입으로 처리됩니다. 리터럴을 long으로 지정하려면 L을 붙이세요. 특히 값이 int 범위를 벗어날 때 필요합니다. 숫자 1과 구별하기 쉬운 대문자 L을 사용하는 편이 좋습니다. 예를 들어 long population = 9_000_000_000L;은 유효한 long 리터럴을 사용합니다. 밑줄은 읽기 쉽게 표시할 뿐 값에는 영향을 주지 않습니다.
int 값과 long 값을 비교하려면 다음 예제를 실행하세요. 예제의 출력 라벨은 영어로 표시되며, 바이트 단위로 보존되어 번역되지 않습니다.
이 섹션의 코드와 표시되는 레이블 또는 출력은 영어로 유지됩니다.
public class IntVsLongExample {
public static void main(String[] args) {
int count = 120;
long total = 9_000_000_000L;
System.out.println("count: " + count);
System.out.println("total: " + total);
}
}
count: 120
total: 9000000000
컴파일 시점의 차이를 보려면 int tooLarge = 2147483648;을 확인하세요. 이 선언은 컴파일되지 않습니다. 10진 리터럴이 int 범위에 들어오지 않으며 long으로 지정하는 접미사도 없기 때문입니다. 대신 long value = 2147483648L;로 작성하세요. 컴파일러는 프로그램이 실행되기 전에 첫 번째 선언을 거부하므로 런타임 출력은 없습니다. 또한 피연산자나 형변환으로 산술 연산이 long이 되지 않는 한 int 식은 int로 계산됩니다. 이미 오버플로가 발생한 결과를 long에 대입해도 손실된 값은 복구되지 않습니다.
Integer 및 Long 래퍼 클래스 사용하기
Integer는 int를 감싸고, Long은 long을 감쌉니다. Java는 오토박싱과 언박싱을 통해 원시 타입과 래퍼 사이의 변환을 지원합니다. 예를 들어 Integer score = 42;는 원시 값을 박싱하고, int recordedScore = score;는 언박싱합니다. 변환을 명시하는 편이 가독성에 도움이 될 때는 intValue()와 longValue() 메서드를 사용할 수도 있습니다.
API가 객체를 요구할 때 래퍼가 유용합니다. 예를 들어 List<Integer>와 같은 제네릭 컬렉션은 원시 타입을 타입 인수로 사용할 수 없으므로, 목록에 넣는 값은 박싱됩니다. long을 객체로 표현해야 한다면 List<Long>처럼 Long을 사용하세요. 일반적인 지역 변수 산술 연산에는 원시 타입이 대체로 더 간단합니다. 변환이나 유틸리티 메서드를 호출하는 것만으로 래퍼 클래스가 필요한 것은 아닙니다.
래핑된 값의 범위는 그대로입니다. Integer는 int 값을 담고 Long은 long 값을 담습니다. 래퍼를 사용해도 기반 원시 타입이 표현할 수 있는 범위를 넘는 숫자를 저장할 수는 없습니다. long 변수에 대입하든 Long으로 박싱하든 long 리터럴에는 L을 붙이세요.
원시 타입과 래퍼 객체의 차이
원시 타입 변수에는 해당 원시 타입의 값이 저장됩니다. 래퍼 변수에는 래퍼 객체를 가리키는 참조나 null이 들어갑니다. 이것이 프로그래밍에서 유용한 구분입니다. 래퍼를 숫자 저장 공간을 가리키는 포인터로만 설명하는 것은 실제 메모리 구조를 부정확하게 묘사하며, 타입 선택에도 도움이 되지 않습니다.
원시 타입에는 null을 대입할 수 없습니다. Integer optionalCount = null;과 같은 참조는 값이 없음을 나타낼 수 있으므로, API나 데이터 모델에서 “제공되지 않음”과 숫자 0을 구분해야 할 때 유용합니다. 이 방식을 사용한다면 값을 쓰기 전에 null인지 확인해야 합니다. Java가 null인 Integer 또는 Long을 언박싱하면 NullPointerException이 발생합니다. 참조가 객체를 가리키는지 확인한 뒤 언박싱하세요.
요약하면 필요한 숫자 범위에 따라 int 또는 long을 선택하고, 객체를 요구하는 API나 컬렉션 또는 null 가능성이 필요할 때 Integer나 Long을 사용하세요. 이렇게 하면 산술 연산과 값이 없는 상태를 명확하게 표현할 수 있습니다.