[Java] Integer.valueOf vs new Integer

히태하태·2025년 5월 20일

JAVA

목록 보기
1/1

Java에서 Integer.valueOf() vs new Integer() — 객체 생성 방식의 차이와 성능 영향
Java에서 정수 값을 객체로 사용할 일이 많습니다. 이때 가장 많이 사용하는 클래스는 Integer인데, 이를 객체로 생성하는 방식에는 두 가지가 있습니다:

Integer a = new Integer(100);
Integer b = Integer.valueOf(100);

겉보기엔 동일한 결과를 만들 것 같지만, 실제로는 동작 방식, 메모리 처리, 성능 등에서 큰 차이를 보입니다. 본 글에서는 Integer.valueOf()와 new Integer()의 차이를 JVM의 내부 구조까지 포함해 자세히 알아보겠습니다.

📌 1. 사용법의 차이: 생성자 vs 정적 팩토리 메서드

Java에서 객체를 생성하는 일반적인 방식은 new 키워드를 사용하는 것입니다.

Integer i1 = new Integer(100);

이 방식은 항상 새로운 Integer 인스턴스를 생성합니다. 반면, valueOf()는 정적(static) 메서드로, 내부적으로 객체 재사용을 시도합니다.

Integer i2 = Integer.valueOf(100);

이 메서드는 단순히 new와 같은 기능을 감싸는 것 같지만, 내부적으로는 매우 다른 처리를 합니다. 이 차이는 특히 많은 수의 정수 객체를 다루는 코드에서 메모리 사용과 성능에 지대한 영향을 줍니다.

🔍 2. 내부 처리 방식: 캐시(Cache) 사용 여부

2.1 new Integer(): 항상 새로운 객체 생성
new Integer()를 사용하면 JVM은 힙 메모리(Heap) 에 새로운 Integer 객체를 생성합니다. 이 객체는 GC(Garbage Collector)에 의해 관리되며, 동일한 값을 갖더라도 참조가 다르므로 == 비교에서는 항상 false가 됩니다.

Integer a = new Integer(100);
Integer b = new Integer(100);
System.out.println(a == b); // false

2.2 Integer.valueOf(): -128 ~ 127 캐시 재사용
valueOf()는 객체 재사용을 위한 캐시 메커니즘을 제공합니다. 이 메서드는 -128부터 127까지의 정수에 대해 미리 만들어진 Integer 객체를 재사용합니다.

Integer x = Integer.valueOf(100);
Integer y = Integer.valueOf(100);
System.out.println(x == y); // true

내부 코드를 보면 다음과 같은 구조입니다:

public static Integer valueOf(int i) {
    if (i >= -128 && i <= 127)
        return IntegerCache.cache[i + 128];
    else
        return new Integer(i);
}

즉, -128~127 범위의 정수는 IntegerCache라는 배열에 미리 만들어 놓고, 동일한 값을 요청하면 해당 객체를 그대로 반환합니다.

🧠 3. JVM 메모리 구조와 객체 위치

이 차이는 JVM의 메모리 영역 구조와도 연결됩니다.

메모리 영역 설명
Heap new 키워드로 생성된 객체가 위치하는 공간. GC 대상.
Method Area 클래스, 정적 변수, 정적 메서드가 저장되는 공간. 정적 캐시도 여기에 위치.
IntegerCache Integer.valueOf()의 캐시 배열. 클래스 로딩 시 Method Area에 위치함.

Integer.valueOf()는 클래스 로딩 시 캐시를 Method Area에 로드하고, 반복적으로 재사용합니다. 반면 new Integer()는 매번 Heap에 새 객체를 생성하므로 GC에 부담을 줍니다.

⚙️ 4. 성능 및 메모리 측면 비교

항목new Integer()Integer.valueOf()
객체 생성 비용높음 (항상 새 인스턴스)낮음 (캐시 활용 시 객체 재사용)
메모리 사용량많음 (중복 객체 다수 존재)적음 (공통 객체 공유)
GC 부담작음
== 비교 가능 여부불가 (false)가능 (true, 캐시 범위 내일 경우)
속도느림 (Heap 할당 + GC 대상)빠름 (캐시 참조만으로 반환)
코드 권장 여부❌ Java 9부터 deprecated✅ 추천되는 표준 방식

결론적으로, Integer.valueOf()는 성능, 메모리 효율성 모두에서 우월하며, new Integer()는 더 이상 사용을 권장하지 않습니다.

🧪 5. 실무 예제 비교

예제 1: 캐시 범위 내 비교

Integer a = Integer.valueOf(100);
Integer b = Integer.valueOf(100);
System.out.println(a == b); // true
System.out.println(a.equals(b)); // true

예제 2: 캐시 범위 외 비교

Integer x = Integer.valueOf(200);
Integer y = Integer.valueOf(200);
System.out.println(x == y); // false
System.out.println(x.equals(y)); // true

예제 3: 오토박싱이 어떻게 동작할까?

Integer a = 100; // 컴파일러가 자동으로 Integer.valueOf(100) 호출
Integer b = 100;
System.out.println(a == b); // true

자동 박싱(Autoboxing)도 내부적으로 valueOf()를 사용하므로 동일한 최적화 혜택을 받습니다.

💡 6. 캐시 범위 확장 (고급)

기본적으로 캐시 범위는 -128 ~ 127로 설정되어 있지만, JVM 옵션으로 확장할 수 있습니다.

-Djava.lang.Integer.IntegerCache.high=1000

이렇게 설정하면 1000까지의 값도 캐싱되어 valueOf() 사용 시 객체를 재사용하게 됩니다. 대량의 정수 객체가 필요한 경우 성능 개선에 도움이 됩니다.

✅ 7. 최종 정리 및 실무 가이드

new Integer()는 매번 새 객체를 만들고 GC 부담이 크므로 사용하지 말 것

Integer.valueOf()는 캐시를 통해 객체를 재사용하므로 성능과 메모리 측면에서 매우 효율적

== 비교를 사용하려면 캐시 범위 내 값만 안전하게 비교 가능 (그 외엔 .equals() 사용)

Java 9부터 new Integer(int) 생성자는 deprecated 되었음

✍️ 마무리

Integer.valueOf()와 new Integer()의 차이는 단순히 객체 생성 방식의 차원을 넘어, JVM의 메모리 구조, 객체 관리 방식, 성능 최적화 등 Java 내부 작동 원리와 깊은 관련이 있습니다. 실무에서 수많은 정수 객체를 다뤄야 한다면, 이 차이를 이해하고 valueOf() 방식으로 코드를 작성하는 것이 메모리 효율성과 성능 개선에 큰 도움이 됩니다.

작은 습관 하나가 전체 시스템의 퍼포먼스를 바꿀 수 있습니다. 언제나 valueOf()를 우선 사용하고, == 대신 .equals()를 기본으로 생각합시다.

profile
시작이 반이다. 일단 시작해보자.

0개의 댓글