상세 컨텐츠

본문 제목

자바 공부#1_02. int vs Integer

카테고리 없음

by 코딩연습중 2025. 3. 26. 15:53

본문

이전 글에서 기본형 vs 참조형에 대해 설명했는데 더 자세히 공부해보겠다.

 

https://codstudy.tistory.com/93

 

자바 공부#1_01. 기본형(Primitive type) vs 참조형(Reference type)

Datatype 종류:1. 기본형(primitive type): 실제 '값' 저장2. 참조형(reference type): 객체의 '주소' 저장.(null 또는 객체의 주소(4byte))  1. 기본형(Primitive type)논리형 - boolean문자형 - char정수형 - byte, short, int, lo

codstudy.tistory.com

 

int vs Integer

타입 기본형 (primitive type) 참조형 (Reference Type, 클래스)
메모리 스택에 저장 힙에 객체로 저장
값의 유효 범위 -2³¹ ~ 2³¹-1 동일
null 허용 ❌ (null 불가) ✅ (null 허용)
객체 메서드 ❌ 사용 불가 ✅ .compareTo(), .equals() 등 사용 가능
컬렉션 사용 ❌ 불가능 (List 불가) ✅ 가능 (List 가능)
연산 방식 기계 수준의 산술 연산 언박싱 후 연산(내부적으로 int로 반환됨)
성능 빠름 느림(오토박싱/언박싱 overhead)

 

자바는 원래 모든 객체는 클래스 기반인데, int는 너무 자주 쓰이니까 특별히 만들어진 기본형.
하지만 자바 컬렉션(List, Set, Map 등)은 객체만 넣을 수 있어서 int는 안 들어감.

List<int> list = new ArrayList<>(); // ❌ 안 됨
List<Integer> list = new ArrayList<>(); // ✅ 됨

 

그래서 int를 객체로 감싼 클래스가 필요한데 → 그게 Integer!

 

 

✅ 언제 뭐 써야 돼?

계산, 성능 중요 int (더 빠름, 가볍고 null 없음)
컬렉션에 넣거나 null 가능성 있음 Integer (List, Map, JSON 등)

 

 

int vs Integer 성능 비교

 

📊 실제 성능 비교 (예: 1000만 번 더하기)

// int 루프
long t1 = System.nanoTime();
int sum1 = 0;
for (int i = 0; i < 10_000_000; i++) sum1 += i;
long t2 = System.nanoTime();

// Integer 루프
long t3 = System.nanoTime();
Integer sum2 = 0;
for (int i = 0; i < 10_000_000; i++) sum2 += i; // 언박싱 + 박싱 발생
long t4 = System.nanoTime();

System.out.println("int time: " + (t2 - t1));
System.out.println("Integer time: " + (t4 - t3));

🧪 결과 (환경에 따라 다르지만):

  • int 루프: 훨씬 빠름
  • Integer: 약 5~10배 느림
    → Integer는 반복문에서 매번 언박싱/박싱이 발생하기 때문

🧨 2. Integer가 null일 때 언박싱 → NPE (NullPointerException)

Integer x = null;
int y = x;  // 💥 여기서 NullPointerException 발생!

😱 왜?

  • int y = x 시도 → 자바는 자동 언박싱을 시도함
  • 하지만 x가 null → null.intValue() 호출하는 셈
  • → 결국 NPE 발생

예시 1: DB 조회 결과

Integer age = user.getAge(); // DB에 null 가능성 있음
int realAge = age + 1;       // 💥 NPE!

해결 방법

int safeAge = (age != null) ? age : 0;

또는

Optional.ofNullable(age).orElse(0);

✅ 상황 별 써야하는 타입

값이 항상 있고, 연산 목적 int (성능 ↑, NPE ↓)
null 가능성 있음 (DB 등) Integer (Wrapper)
컬렉션 요소로 사용 Integer (List<Integer> 등)

🎯 핵심 정리

항목 핵심 내용

int vs Integer 성능 int가 훨씬 빠르다 (루프/연산 최적화)
Integer가 null일 때 언박싱 시 NPE 터짐 (주의!)
중요 팁 연산용은 무조건 int, null 가능 시엔 Integer + null 체크 필수

필요하면:

  • Integer 캐싱 범위 (-128 ~ 127) 관련 트릭
  • Wrapper 클래스 equals vs == 비교
  • Optional 처리 팁

도 같이 정리해줄게! 😎
이해된 거 같아? 예외 실습 코드 만들어볼까?

 

 

그럼 DB의 INT 타입은 int vs Integer 뭐랑 매핑?

INT (NOT NULL) int
INT (nullable) Integer ✔

자바에서는 DB 값이 null 가능성 있을 때 → Wrapper 클래스(Integer)
NOT NULL 컬럼이면 → int 써도 됨

→ JPA나 MyBatis도 기본적으로 nullable이면 Integer로 매핑


✅ 대량 데이터를 다룰 때는 Integer가 맞을까?

대량 데이터 + 연산 없음 + null 가능성 있음 ✅ Integer (컬렉션에 넣고 꺼낼 수 있음)
대량 데이터 + 전부 값 있음 (NOT NULL) int도 가능하지만, null 안전성 위해 Integer 쓰는 경우 많음

 


✅ 1. Integer 캐싱 범위 (-128 ~ 127)

🔍 무슨 말이냐면?

자바는 자주 쓰는 정수 값을 메모리 절약 + 성능 향상을 위해
-128 ~ 127 범위의 Integer 객체는 미리 캐싱해두고 재사용

Integer a = 100;
Integer b = 100;
System.out.println(a == b); // ✅ true → 같은 객체 (캐싱)

Integer c = 1000;
Integer d = 1000;
System.out.println(c == d); // ❌ false → 다른 객체 (캐싱 범위 벗어남)

📌 왜 이게 중요한가?

== 비교는 값이 아닌 객체 주소를 비교하니까,
캐싱 범위 안에 있으면 동일 객체로 참조됨 → true,
범위를 넘으면 new Integer()처럼 따로 생성됨 → false

 

Integer a = 128;
Integer b = 128;

System.out.println(a == b);         // false (다른 객체)
System.out.println(a.equals(b));    // true  (값은 같음)

 

❗ 항상 equals()로 비교해야 안전해!


✅ 2. Map에서 Integer 키와 int 비교 주의

🔍 왜 주의해야 하냐면?

Map<Integer, String> map = new HashMap<>();
map.put(1000, "hello");

System.out.println(map.get(1000));           // ✅ 잘 나옴
System.out.println(map.get(new Integer(1000))); // ✅ 이것도 됨 (equals 비교)

Integer a = 1000;
Integer b = 1000;
System.out.println(a == b); // ❌ false

System.out.println(map.get(a)); // ✅ 그래도 잘 나옴 (equals 사용)

📌 핵심은:

  • Map.get()은 내부적으로 **equals()와 hashCode()**를 사용한다.
  • 그래서 int, Integer, new Integer(...) 다 같은 값이면 동작은 잘 돼.
  • 하지만 ==로 비교하면 캐싱 범위에 따라 결과가 달라질 수 있어서 혼란 발생!

🧠 실무 팁 정리

비교 방식 안전 여부 이유

== ❌ 위험함 객체 주소 비교 → 캐싱 범위 영향
equals() ✅ 안전함 값 비교 (Object 동등성)
Map<Integer, ...>에서 키 비교 ✅ 문제 없음 hashCode + equals 사용
switch(Integer) ✅ 자동 언박싱 → int로 처리됨 (괜찮음)  

🎯 결론 요약

항목 주의사항

Integer는 -128~127까지만 캐싱 이 범위 안에서는 ==로 비교해도 true 나올 수 있음
그 외는 새로운 객체 생성됨 == 비교하면 false 나옴 (주소 다름)
항상 equals()로 비교하자! 객체 비교에서는 == 절대 쓰지 마!
Map<Integer, V>는 안전함 내부적으로 equals()와 hashCode()를 쓰기 때문에 값만 같으면 됨