Wrapper 클래스란?
자바의 자료형은 크게 기본 타입(primitive type)과 참조 타입(reference type)으로 나누어진다. 기본 타입은 char, int, float, double, boolean 등이 있고 참조 타입은 class, interface 등이 있는데 프로그래밍을 하다 보면 기본 타입의 데이터를 객체로 표현해야 하는 경우가 종종 있다.
자바의 Wrapper 클래스는 기본 자료형(Primitive Type)을 객체(Object)로 감싸는 클래스이다. 기본형 데이터를 객체로 다뤄야 할 때 사용되며, java.lang 패키지에 포함되어 있다.
기본 자료형(primitive type) - Wrapper 클래스
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
기본형이랑 객체랑 뭐가 다르길래 객체로 다뤄야할 필요가 생기는 걸까?
자바에서 기본형(int, double, char 등)은 객체가 아닌 단순한 값이다.
반면, 객체(Object)는 클래스 기반으로 생성된 인스턴스로, 속성(필드)과 동작(메서드)을 가질 수 있다.
즉, 기본형을 객체처럼 다룬다는 건,
✔ 기본형 데이터를 객체 형태로 감싸서(Wrapping) 사용할 수 있도록 하는 것
✔ 객체가 제공하는 메서드와 컬렉션(List, Map 등) 사용이 가능하게 하는 것
기본형 vs 객체(Wrapper 클래스) 차이
❌ 기본형(int) → 객체처럼 다룰 수 없다
int num = 100;
System.out.println(num.toString()); // ❌ 컴파일 에러 (기본형은 메서드 없음)
📌 int는 단순한 숫자 데이터이기 때문에 객체처럼 메서드를 가질 수 없음
✅ 기본형을 객체(Integer)로 다루기
Integer num = 100; // 기본형 int를 객체(Integer)로 감쌈
System.out.println(num.toString()); // ✅ 가능! "100"
📌 Integer는 객체이므로 메서드(toString())를 사용할 수 있음
기본형을 객체로 다루는 Wrapper 클래스의 특징
(1) 객체이므로 메서드 사용 가능
int num1 = 10;
Integer num2 = 20;
System.out.println(num2.toString()); // "20" (Wrapper 클래스는 toString() 사용 가능)
System.out.println(Integer.max(10, 20)); // 20 (최대값 구하는 메서드)
public class WrapperMethods {
public static void main(String[] args) {
// 문자열을 숫자로 변환
int num = Integer.parseInt("123");
double dNum = Double.parseDouble("3.14");
// 숫자를 문자열로 변환
String strNum = Integer.toString(100);
String strDNum = Double.toString(10.5);
System.out.println(num); // 123
System.out.println(dNum); // 3.14
System.out.println(strNum); // "100"
System.out.println(strDNum); // "10.5"
}
}
✔ 기본형에서는 불가능한 메서드 호출이 가능해짐
(2) 컬렉션(List, Map 등) 사용 가능
자바의 컬렉션(List, Map, Set 등)은 기본형을 저장할 수 없고, 객체만 저장 가능하다
Wrapper 클래스를 사용하면 기본형을 객체처럼 저장할 수 있다
List<int> list = new ArrayList<>(); // ❌ 불가능 (기본형 사용 불가)
List<Integer> list = new ArrayList<>(); // ✅ 가능 (Wrapper 클래스 사용)
list.add(10);
list.add(20);
✔ 기본형 int를 직접 넣을 수 없지만, Integer 객체로 변환하면 리스트에 저장 가능
(3) null 값을 저장할 수 있음
기본형은 null을 가질 수 없지만, 객체는 가능하다
int num1 = null; // ❌ 오류 (기본형은 null 저장 불가)
Integer num2 = null; // ✅ 가능 (Wrapper 클래스는 객체이므로 null 저장 가능)
✔ Wrapper 클래스를 사용하면 "아직 값이 없음"을 표현할 수 있음
즉, 기본형을 객체로 다룬다는 것은?
✔ 기본형을 객체처럼 감싸(Wrapping)서 객체의 장점을 활용
✔ 메서드 사용 가능 → toString(), parseInt() 같은 기능을 사용할 수 있다
✔ 컬렉션(List, Map 등) 사용 가능 → 기본형은 컬렉션으로 저장할 수 없지만, Wrapper 클래스는 가능
✔ null 저장 가능 → 기본형은 불가능하지만, Wrapper 클래스는 가능
🚀 결론은 기본형을 객체처럼 다루면 객체 지향적 프로그래밍이 가능하고, 컬렉션 활용도 가능해진다! 🎉
자동 박싱(Auto-Boxing) / 언박싱(Auto-Unboxing) 지원
public class WrapperExample {
public static void main(String[] args) {
// Auto-Boxing (기본형 → Wrapper 객체)
Integer num = 10; // Integer.valueOf(10)과 동일
// Auto-Unboxing (Wrapper 객체 → 기본형)
int value = num; // num.intValue()와 동일
System.out.println(num + 5); // 자동으로 unboxing 되어 연산 가능
}
}
Java 5부터 기본형과 Wrapper 클래스 간 변환이 자동으로 이루어진다.
Wrapper 클래스의 비효율성
Wrapper 클래스를 사용하는 이유는 있지만, 동시에 몇 가지 비효율성과 불편함도 있다.
기본형(int, double 등)은 가볍고 빠른데 반해, Wrapper 클래스(Integer, Double 등)는 객체 생성 비용과 메모리 사용량이 증가하기 때문
🚨 (1) 객체 생성 비용 증가
Wrapper 클래스는 Heap 메모리에 객체를 생성하기 때문에, 기본형보다 메모리 사용량이 크고 속도가 느리다.
int a = 10; // Stack 메모리 사용, 빠름
Integer b = new Integer(10); // Heap 메모리 사용, 비효율적 (권장하지 않음)
📌 Integer b = 10;처럼 하면 Integer.valueOf(10)을 사용해 객체 풀(Cached Pool)에서 재사용하지만, 여전히 기본형보다 무겁다.
🚨 (2) 연산 속도 저하
기본형은 CPU가 직접 연산하지만, Wrapper 클래스는 Auto-Boxing & Unboxing 과정이 필요해 성능이 떨어질 수 있다
Integer num1 = 1000;
Integer num2 = 1000;
System.out.println(num1 == num2); // false (객체 비교)
System.out.println(num1.equals(num2)); // true (값 비교)
📌 Integer는 객체 비교 시 주소를 비교하므로 예상과 다른 결과가 나올 수 있다
🚨 (3) Auto-Boxing & Auto-Unboxing 오버헤드
Auto-Boxing(기본형 → Wrapper)과 Auto-Unboxing(Wrapper → 기본형)이 자주 발생하면 성능에 영향을 줄 수 있다
public class BoxingExample {
public static void main(String[] args) {
long start = System.nanoTime();
Long sum = 0L; // Wrapper 클래스 사용
for (long i = 0; i < 1_000_000; i++) {
sum += i; // Auto-Unboxing & Auto-Boxing 반복 발생
}
long end = System.nanoTime();
System.out.println("Time: " + (end - start) + " ns");
}
}
📌 sum += i;에서 sum은 Long(객체)인데, i(기본형)와 연산하려면 Unboxing 후 연산하고 다시 Boxing해야 해서 성능이 떨어짐.
✔ 해결 방법: long sum = 0;으로 기본형을 사용하면 훨씬 빠름!
그럼에도 Wrapper 클래스를 써야 하는 이유는?
✔ (1) 컬렉션(List, Set, Map 등)에 기본형 저장 불가
자바의 컬렉션 프레임워크는 객체(Object)만 저장할 수 있다
List<Integer> list = new ArrayList<>(); // ✅ Integer는 객체라 가능
list.add(10); // Auto-Boxing (int → Integer)
List<int> list = new ArrayList<>(); // ❌ 컴파일 에러 (기본형 저장 불가)
✔ (2) 객체 지향적인 API 사용 가능
Wrapper 클래스는 다양한 메서드와 상수를 제공해 편리하다
int max = Integer.max(10, 20); // 20 반환
boolean isTrue = Boolean.parseBoolean("true"); // true 반환
✔ (3) 멀티스레드 환경에서 동기화 지원
기본형은 동기화가 불가능하지만, Wrapper 클래스는 **Immutable(불변 객체)**이라 스레드 안정성이 더 좋다
결론: 기본형과 Wrapper 클래스 언제 써야 할까?
🚀 기본형 (Primitive) vs Wrapper 클래스 (Object)
속도가 빠름, 메모리 사용량 적음 | 객체로 다룰 수 있어 컬렉션에 사용 가능 |
수치 연산에 적합 | null 저장 가능 (기본형은 null 불가능) |
불필요한 Boxing/Unboxing 없음 | 다양한 메서드 제공 (ex: Integer.parseInt()) |
💡 정리
- 성능이 중요한 연산 → 기본형 사용 (int, double 등)
- 컬렉션 사용 → Wrapper 클래스 사용 (Integer, Double 등)
- 값이 null이 될 가능성이 있으면 → Wrapper 클래스 사용
✔ 가능하면 기본형을 사용하되, 객체를 필요로 하는 경우에만 Wrapper 클래스를 활용하는 것이 효율적이다
'Language > JAVA' 카테고리의 다른 글
[Spring] Web Server vs WAS (Web Application Server) (0) | 2025.03.24 |
---|---|
[JAVA] 입력 (0) | 2024.11.19 |
[명품 JAVA programming] CHAPTER 4 클래스와 객체(실습문제) (0) | 2023.03.19 |
[명품 JAVA programming] CHAPTER 4 클래스와 객체 (0) | 2023.03.19 |
[명품 JAVA programming] CHAPTER 3 반복문과 배열 그리고 예외 처리(실습문제) (0) | 2023.02.24 |