백엔드 스터디를 진행하며 long
과 Long
의 차이가 무엇인지에 대해 질문을 받았을 때는 저도 대답하기 힘들더군요... Java에서는 기본 자료형과 래퍼 클래스 간의 차이를 이해하는 것이 성능 최적화와 메모리 관리에 도움이 된다는 것을 기억하며 이번 글에서는 그 중 하나인 long
과 Long
의 주요 차이점과 사용 시 주의 사항을 정리해보겠습니다.
long
: 기본 자료형(primitive type)으로 실제 값을 저장합니다. long
은 메모리에 직접 값이 저장되며, 기본 연산이 빠릅니다.Long
: 래퍼 클래스(wrapper class)로, 객체(Object)입니다. 기본 자료형인 long
을 객체로 감싸는 클래스이며, 다양한 메서드를 제공합니다. Long
객체는 힙 메모리에 저장됩니다.long
: 기본값은 0
입니다. 예를 들어, long
변수를 선언하면 자동으로 0
으로 초기화됩니다.Long
: 객체이므로 기본값은 null
입니다. Long
객체를 선언하고 초기화하지 않으면 null
을 가질 수 있습니다.long
: 고성능이 필요하거나 객체 생성을 피하고자 할 때 주로 사용됩니다.Long
: 컬렉션 프레임워크(예: ArrayList
, HashMap
) 같은 객체를 필요로 하는 경우에 사용됩니다. 예를 들어, ArrayList<Long>
는 가능하지만 ArrayList<long>
는 불가능합니다. Stream<Long>
과 같은 경우에도 마찬가지로 Long
타입이 필요합니다.long
값을 Long
객체로 변환합니다.long primitiveLong = 10L;
Long wrapperLong = Long.valueOf(primitiveLong); // 박싱
Long wrapperLong = 10L;
long primitiveLong = wrapperLong.longValue(); // 언박싱
Java 컴파일러는 기본 자료형과 래퍼 클래스 간의 변환을 자동으로 수행합니다. 이를 통해 코드가 간결해집니다.
Long wrapperLong = 10L; // 자동 박싱
long primitiveLong = wrapperLong; // 자동 언박싱
💡 자동 박싱과 언박싱은 편리하지만, 반복문에서 빈번하게 발생할 경우 성능에 영향을 줄 수 있습니다. 예를 들어, 대규모 반복 작업에서 자동 박싱을 최소화하면 성능을 최적화할 수 있습니다.
long
은 스택 메모리에 직접 저장되며 메모리를 효율적으로 사용합니다.Long
은 객체이므로 힙 메모리에 저장되고, 참조를 통해 접근합니다. 따라서 long
에 비해 메모리를 더 많이 사용합니다.💡 메모리 관리가 중요한 상황이라면 기본 자료형인
long
을 사용하는 것이 유리합니다.
long
타입은 null 값을 가질 수 없습니다. 따라서 long
변수가 null로 초기화되는 경우는 없습니다.Long
타입은 null 값을 가질 수 있어 널 포인터 예외(NullPointerException)가 발생할 수 있습니다. 예를 들어:Long wrapperLong = null;
long primitiveLong = wrapperLong; // NullPointerException 발생 가능
💡 Null 값이 필요한 경우 Optional을 사용해 널 포인터 예외를 예방하는 방법도 고려해 볼 수 있습니다.
Long.valueOf(primitiveLong)
은 박싱 메서드로, 내부적으로 -128
에서 127
까지의 값을 캐싱해 재사용합니다. 이로 인해 작은 값들을 사용할 때 메모리를 절약할 수 있습니다. 이 점을 고려해 자주 사용하는 작은 값 범위 내에서는 성능 이점이 있습니다.
💡 정리: 일반적으로
long
은 성능과 메모리 효율이 중요한 경우에 사용되고,Long
은 컬렉션과 같은 객체를 필요로 하는 상황에서 사용됩니다. 기본 자료형과 래퍼 클래스의 차이점을 명확히 이해하고, 각 상황에 맞게 사용하는 것이 중요합니다.