| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |
- 취약점
- 이클립스
- 윈도우11
- 페이스북서명운동
- 다음아고라서명운동
- 컨택리스
- 토큰탈취
- Applepay
- 베이직쎈
- 내방문자찾아주오
- 랜섬웨어
- 페이스북
- 젤프
- 토큰털이
- 자바
- perplexity
- 방문자추적기
- 2017티스토리결산
- 2017 티스토리 결산
- 다음아고라사칭
- 애플페이
- 토스뱅크
- 예제
- 티스토리
- 메플리
- 0원메가패스
- ChatGPT
- wannacry
- zelf
- Ai
- Today
- Total
EdgeSecu
래핑, 박싱 하는 이유 + 제네릭에 기본형을 못 쓰는 이유 본문
1. 제네릭에 primitive를 못 쓰는 이유
- 타입 소거(Type Erasure)
- 자바의 제네릭은 런타임에 타입 정보를 지우고(Object로 치환) 컴파일 시점에만 타입 안전성을 체크해.
- 예를 들어 List<String> → 실제 바이트코드상에는 List 로만 남고, 내부에는 Object 타입 요소를 저장
- primitive는 Object에 담을 수 없기 때문에, 제네릭 파라미터로 primitive를 허용할 수 없어
- 하위 호환성(Backward Compatibility)
- 제네릭은 자바 5에서 도입됐는데, 이전 버전과의 호환성을 위해 타입 소거 방식을 선택
- 만약 List<int> 처럼 primitive 전용 바이트코드를 만들면, 기존 자바 라이브러리와 충돌이 나기 쉬워
- 참조형만 타입 파라미터로 허용
- 자바 문법상 타입 파라미터 <T>는 “참조형(reference type)”만 가능
- T extends Number 같은 제한은 가능하지만, int는 클래스가 아니기 때문에 지정 불가
2. 박싱(Boxing)·래핑(Wrapping)의 필요성
2.1 왜 래퍼(wrapper) 클래스가 필요한가?
- primitive는 힙에 객체처럼 저장되지 않고, 스택이나 레지스터에 값으로만 다뤄짐
- 컬렉션(List, Map 등)이나 리플렉션, 제네릭 같은 API는 모두 객체(Object) 만 다루도록 설계됨
- 그래서 primitive를 객체처럼 쓰려면 Integer, Double 같은 래퍼 클래스로 “감싸는(wrap)” 과정이 필요
2.2 박싱(Boxing) vs 언박싱(Unboxing)
- 박싱(Boxing): primitive → 래퍼
-
java복사편집int i = 5; Integer wi = Integer.valueOf(i); // 수동 박싱
- 언박싱(Unboxing): 래퍼 → primitive
-
java복사편집Integer wi = Integer.valueOf(10); int i = wi.intValue(); // 수동 언박싱
2.3 오토박싱/오토언박싱
- 자바 5부터는 컴파일러가 박싱·언박싱 코드를 자동으로 삽입해 줌
-
java복사편집Integer wi = 20; // → Integer.valueOf(20) int i = wi; // → wi.intValue()
- 장점: 코드가 훨씬 간결
- 단점:
- 매번 객체를 생성(또는 캐시 활용)하므로 성능 오버헤드
- 언박싱 시 null 래퍼가 들어오면 NPE 발생
3. “왜 이런 과정을 거칠까?”
- 일관된 API 설계
- 모든 자료구조, 제네릭, 리플렉션 API를 “객체” 기반으로 통일
- primitive만 예외로 두면 API가 복잡해지고 특수 처리 코드를 더 많이 써야 함
- 타입 안전성과 재사용성
- 래퍼 클래스를 쓰면 오토박싱 없이도 객체 메서드(equals(), toString() 등)를 활용 가능
- 제네릭으로 List<T> 같은 코드를 한 번만 작성하고, 다양한 참조형에 재사용
- 언어 발전 단계
- 초기 자바는 primitive만 집중했지만, 발전하면서 컬렉션·제네릭 중심으로 패러다임이 바뀜
- 기존 코드를 깨뜨리지 않고 새로운 기능을 추가하려다 보니 박싱/타입 소거 방식을 택하게 된 거
정리
- 제네릭은 런타임에 타입 정보를 지우는 설계(타입 소거) 때문에 primitive 파라미터 불가
- 박싱/언박싱은 primitive를 객체 API에 끼워 쓰기 위한 변환 과정
- 오토박싱은 편의성을 위해 컴파일러가 자동으로 코드를 넣어 주는 문법적 설탕
이 과정 덕분에 자바에서 일관된 컬렉션·제네릭·리플렉션 API를 쓸 수 있지만, 성능과 NPE 위험은 염두에 둬야 해.
자바에서 박싱/언박싱과 오토박싱/언박싱을 사용하는 이유는 기본형 타입의 한계를 극복하고 객체 지향 프로그래밍의 이점을 활용하기 위해서입니다.
기본형 타입의 한계
자바는 객체 지향 언어이지만, 성능상의 이유로 int, double, boolean 같은 기본형 타입을 제공합니다[1]. 하지만 기본형은 객체가 아니기 때문에 다음과 같은 한계가 있습니다[1]:
· null 값을 가질 수 없음: 기본형은 항상 값을 가져야 하므로 "데이터가 없음"을 표현할 수 없습니다
· 컬렉션 사용 불가: ArrayList<int>처럼 컬렉션의 제네릭 타입으로 사용할 수 없습니다
· 객체의 메서드 사용 불가: 기본형은 메서드를 가지지 않아 객체 지향적 기능을 활용할 수 없습니다
래퍼 클래스의 필요성
이런 문제를 해결하기 위해 자바는 기본형에 대응하는 래퍼 클래스를 제공합니다[2]:
| 기본형 | 래퍼 클래스 |
| int | Integer |
| double | Double |
| boolean | Boolean |
| char | Character |
· null 값 표현 가능: 데이터가 없는 상태를 명확히 표현할 수 있습니다
· 컬렉션 사용 가능: ArrayList<Integer>처럼 컬렉션에서 사용할 수 있습니다
· 객체 메서드 활용: toString(), equals() 등의 메서드를 사용할 수 있습니다
· 문자열 변환: Integer.parseInt("123")처럼 문자열을 기본형으로 변환할 수 있습니다[2]
오토박싱/언박싱의 편의성
초기에는 기본형과 래퍼 클래스 간 변환을 수동으로 해야 했습니다[3][2]:
// 수동 박싱/언박싱
int i = 10;
Integer num = new Integer(i); // 박싱
int n = num.intValue(); // 언박싱
하지만 JDK 1.5부터 오토박싱과 오토언박싱이 도입되어 컴파일러가 자동으로 변환해줍니다[3][4]:
// 오토박싱/언박싱
Integer num = 10; // 자동 박싱
int i = num; // 자동 언박싱
이를 통해 개발자는 더 간결하고 읽기 쉬운 코드를 작성할 수 있게 되었습니다[5].
주요 사용 사례
컬렉션 프레임워크: List<Integer>에 int 값을 추가할 때 자동으로 박싱이 발생합니다[6][5]:
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
list.add(i); // 오토박싱 발생
}
null 처리: 데이터베이스에서 값이 없을 수 있는 경우 래퍼 클래스를 사용합니다[1]:
Integer age = null; // 나이 정보가 없음을 표현
성능상 주의점
편의성을 제공하지만 성능상 비용이 발생할 수 있습니다[3][6][5]:
· 객체 생성 비용: 박싱 시마다 새로운 객체가 생성됩니다
· 메모리 사용량 증가: 래퍼 객체는 기본형보다 더 많은 메모리를 사용합니다
· 가비지 컬렉션 부담: 불필요한 객체 생성으로 GC 부담이 증가할 수 있습니다
성능 테스트 결과, 100만 건 기준으로 약 5배의 성능 차이가 발생할 수 있습니다[3]. 따라서 대량의 데이터를 처리하거나 성능이 중요한 경우에는 기본형 타입을 사용하는 것이 좋습니다[3][5].
결론적으로, 박싱/언박싱은 자바의 객체 지향적 특성과 기본형의 성능상 이점을 모두 활용하기 위한 메커니즘이며, 오토박싱/언박싱은 개발자의 편의성을 높이기 위해 도입된 기능입니다.
'공부 > JAVA' 카테고리의 다른 글
| 함수형 인터페이스와 SAM의 차이 (0) | 2025.05.26 |
|---|---|
| static에 관하여 (0) | 2025.05.17 |
| final에 관하여 (0) | 2025.05.17 |
| JAVA-네트워크 자원 정리 (0) | 2025.05.16 |
| JAVA try-with-resources(자동 자원 해제) (0) | 2025.05.13 |