[Java] Integer가 있는데 int를 왜 쓰나요? / 래퍼 클래스(wrapper class)에 대하여
이 글의 목차14개
✍️ 서론
나는 알고리즘을 공부하며 늘 한 가지 의문점이 있었다.
왜
int형이 존재하는 것일까?
Integer는 다양한 기능도 많고 형변환도 쉽고 null도 담을 수 있는데
왜 int를 사용해야 하는 것일까? 왜 둘은 나누어져 있는 것일까?
지금부터 그 질문에 대한 해답을 정리하려고 한다.
✅ int와 Integer는 무엇이고, 무엇이 다른가?
자바에서는 정수를 표현할 때
int와 Integer라는 두 가지 타입이 존재한다.
그렇기에 나는 자바를 공부하며 이런 궁금증이 생겼다.
“숫자를 저장하는데 왜 타입이 두 개나 필요하지?”
처음엔 “Integer가 더 고급진 타입이겠지~” 라고 생각하고 지나쳤지만
실제로 이 둘은 의미부터, 저장 방식, 동작까지 완전히 다르다는 것을 알게되었다.
🔹 int는 기본형(Primitive Type)
int는 자바에서 제공하는 기본 데이터 타입 중 하나다.
8개의 기본형 타입 중 하나고,
말 그대로 “숫자 그 자체”를 저장하는 타입이다.
int a = 10;
- 여기서
a는 숫자 10을 값 자체로 저장한다. - 메모리의 스택(stack) 영역에 바로
10이라는 숫자가 올라감 - null 값을 가질 수 없음
🔸 Integer는 참조형(Reference Type), 즉 객체다
반면 Integer는 클래스다.
java.lang.Integer라는 이름을 가진 래퍼 클래스(Wrapper Class) 이고,
내부적으로는 int value라는 필드를 갖고 있다.
Integer b = 10;
- 이건
int가 아니라 Integer라는 객체를 만들어서 그 안에 10을 넣는 것 - 메모리에는 스택에는 객체의 주소, 힙에는 실제 Integer 객체가 존재
null을 저장할 수 있음 (Integer b = null;)
✨ 정리
| 구분 | int | Integer |
|---|---|---|
| 타입 | 기본형 (primitive) | 참조형 (reference) |
| 저장 위치 | 스택에 값 직접 저장 | 스택에 주소, 힙에 객체 저장 |
| null 허용 | ❌ 불가능 | ✅ 가능 |
| 메서드 제공 | ❌ 없음 | ✅ .compareTo(), .toString() 등 |
| 컬렉션 사용 | ❌ 불가 (List |
✅ 가능 (List |
✨ 그렇다면 int가 Integer보다 우월한 상황은 언제일까?
1. 🔥 성능이 중요한 반복 연산
int sum = 0;
for (int i = 0; i < 1_000_000; i++) {
sum += i;
}
이 코드를 Integer로 바꿔본다면?
Integer sum = 0;
for (int i = 0; i < 1_000_000; i++) {
sum += i; // 오토언박싱 + 덧셈 + 오토박싱 반복
}
🚨 내부적으로 계속 int → Integer, Integer → int 변환이 일어나기 때문에
객체 생성 + GC(Garbage Collector) 부담이 크다.
2. 💡 null이 절대 들어오면 안 되는 상황
int는 기본형이라서 null 자체가 들어올 수 없음- 반면
Integer는 참조형이라서 null 참조 시 NPE(Null Pointer Exception) 발생 가능
그래서 “절대로 null이 들어오면 안 되는 필드”는 int로 선언하는 게 안전하다.
3. ✏️ 단순 수학 계산만 필요할 때
int는 연산자+, , ,/이 바로 적용됨Integer는 내부적으로 언박싱을 거쳐야 계산 가능
int result = (a + b) * c;
Integer로 쓰면 결국 내부에서 intValue() 꺼내서 연산하고
다시 Integer로 감싸야 한다. → 부하 발생
4. 🧼 메모리 사용량을 줄여야 할 때
int는 4바이트 (32bit)Integer는 객체니까 내부적으로 추가적인 메모리 구조를 가짐 (객체 헤더 등)
int[] arr = new int[1000000]; // 4MB
Integer[] arr = new Integer[1000000]; // 최소 16MB 이상 (객체 100만 개)
✅ 박싱, 언박싱, 그리고 오토박싱이란?
앞에서 int는 값이고 Integer는 객체라는 것을 정리했다.
이 두 타입은 자동, 혹은 수동으로 변환되기도 하는데
이걸 바로 박싱(Boxing), **언박싱(Unboxing)**이라고 부른다.
그리고 이것이 자동으로 일어나는 걸 **오토박싱(Auto Boxing)**이라고 한다.
🟦 박싱(Boxing)
기본형 → 참조형으로 바꾸는 것
즉, int를 Integer로 감싸는 것.
int a = 10;
Integer b = Integer.valueOf(a); // 박싱 (수동)
int값 10을Integer객체로 감쌌다.- 내부적으로는
new Integer(a)대신 **Integer.valueOf(a)*가 사용된다.
🟨 언박싱(Unboxing)
참조형 → 기본형으로 바꾸는 것
즉, Integer를 다시 int로 꺼내는 것.
Integer a = Integer.valueOf(10);
int b = a.intValue(); // 언박싱 (수동)
Integer안에 들어 있는 int 값을 꺼낸다..intValue()같은 메서드를 통해 꺼냄.
🟩 오토박싱 / 오토언박싱
자바가 알아서 박싱/언박싱을 해주는 기능
int a = 10;
Integer b = a; // 오토박싱
Integer c = 20;
int d = c; // 오토언박싱
a가 자동으로Integer.valueOf(a)로 감싸짐c가 자동으로c.intValue()로 꺼내짐- 자바 컴파일러가 자동으로 해주는 기능이라 굉장히 자주 쓰인다
⚠️ 오토박싱 주의사항
오토박싱은 편하지만, 비용이 있다.
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
list.add(i); // 오토박싱 100만 번 발생
}
- 이 코드는
int→Integer로 100만 개 객체를 만들게 된다. - 즉, 메모리와 성능에 영향을 줄 수 있음
그래서 반복문, 연산이 많을 땐 기본형 int 사용이 훨씬 효율적이다.
✅ 객체에서의 비교연산자와 캐싱
Integer 끼리 == 비교 연산자를 이용하여 비교하면 잘못된 결과가 나올 수 있다는 것을 알게 되었다.
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true?
Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false?
Integer에 100을 할당하고 비교할 땐 true가 반환되지만, 200을 할당하는 경우 false가 반환될 수 있다.
이유가 무엇일까?
🧊 자바는 -128 ~ 127 사이의 Integer를 캐싱한다
이것은 자바의 성능 최적화 전략이다.
자바는 Integer.valueOf(int)를 호출할 때
-128부터 127 사이의 값은 미리 만들어둔 객체를 재사용한다.
Integer a = 100;
Integer b = 100;
// 같은 객체를 참조함 → a == b → true
Integer c = 200;
Integer d = 200;
// 서로 다른 객체를 새로 생성 → c == d → false
이걸 **Integer 캐시(Integer Cache)**라고 부른다.
🔍 내부적으로는 이렇게 동작한다
public static Integer valueOf(int i) {
if (i >= -128 && i <= 127)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
즉, 캐시 범위 안에 들어오면 같은 객체,
범위를 벗어나면 새로운 객체가 생성된다.
❗ ==와 equals중 어떤 것을 사용해야 할까?
==는 객체가 같은지를 비교한다 (주소 비교).equals()는 값이 같은지를 비교한다.
Integer a = 128;
Integer b = 128;
System.out.println(a == b); // false ❌
System.out.println(a.equals(b)); // true ✅
a == b→ 서로 다른 객체니까 falsea.equals(b)→ 내부 값이 같으니까 true
🌟 후기
나는 알고리즘을 공부하며 자바라는 언어에 대해서 잘 알고 있다고 생각했지만, 전혀 아니었던 것 같다. 자바의 원리, 설계 철학, 메모리 관리 등에 대해서도 열심히 공부해야겠다.