J-S-11 String의 특징과 Wrapper Class
글 정보
- 카테고리
- Programming/Java/Starter
- 태그
- JavaLevel2
1. String과 상수 풀 (String Constant Pool)
String의 특징과 메모리 관리
자바의 문자열(String)은 불변(Immutable) 구조를 가집니다.
모든 문자열 리터럴은 상수 풀(String Constant Pool)에 저장됩니다.
동일한 문자열 리터럴("")을 생성하면, 풀 내의 같은 객체를 참조하게 만듭니다.
- 이를 통해 메모리 낭비를 방지합니다.
- 동일한 데이터에 대한 중복 공간 할당을 허용하지 않습니다.
String.intern() 메서드
Native 메서드로 구현되어 있습니다.
- 자바 외부(C언어 등)에서 수행되므로 시스템 리소스와 밀접한 관계가 있습니다.
리터럴("")로 상수를 선언하면 내부적으로 intern()이 호출됩니다.
- 예:
String s1 = "Hello";
[동작 원리]
- 상수 풀에서 해당 리터럴 문자열을 검색합니다.
- 있으면: 이미 생성된 인스턴스를 반환합니다.
- 없으면: 새로 생성하여 풀에 추가한 뒤 반환합니다.
메모리 위치의 변화 (Java 7 전후)
Java 7 이후, 문자열 상수 풀의 위치가 변경되었습니다.
- 기존: PermGen (Permanent Generation) 영역
- 변경: Heap 영역
이로 인해 상수 풀에 저장된 문자열도 GC(Garbage Collection)의 대상이 됩니다.
- 메모리 관리가 더욱 효율적으로 개선되었습니다.
상수 풀(Constant Pool)의 흐름과 생명주기
"A String Literal is always of type String"
문자열 상수는 시점에 따라 다른 공간을 거쳐갑니다.
- 컴파일 타임 (Compile Time)
.class파일 내의 Constant Pool에 저장됩니다.- 로딩 타임 (Loading Time)
- 클래스 로드시 Runtime Constant Pool (Method Area)로 이동합니다.
- 실행 타임 (Runtime)
- 실제 코드 실행 시 String Constant Pool (Heap Area)로 이동합니다.
- 이때
intern()메서드를 통해 중복 제거 및 캐싱이 이루어집니다.

2. StringBuilder: 가변(Mutable) 문자열
개요
불변(Immutable)인 String의 단점을 해결하기 위해 등장했습니다.
- 문자열 연산이 잦을 때 발생하는 메모리 낭비를 줄여줍니다.
핵심 특징
가변(Mutable) 객체입니다.
값 변경 시 임시 객체를 생성하지 않습니다.
- String은 연산 시마다 새로운 객체를 만들지만, StringBuilder는 인스턴스 메모리를 직접 수정합니다.
[주요 메서드]
append(): 문자열 뒤에 내용 추가insert(): 특정 위치에 내용 삽입delete(): 내용 삭제reverse(): 문자열 뒤집기toString(): String 객체로 변환
성능 및 사용 가이드
String과 비교했을 때 연산 속도 차이가 압도적입니다.
문자열 변경이 잦은 로직에서는 반드시 사용해야 합니다.
[참고] StringBuilder vs StringBuffer
- StringBuilder: 동기화(Synchronization) 미지원 → 싱글 스레드 환경에서 가장 빠름.
- StringBuffer: 동기화 지원 → 멀티 스레드 환경에서 안전(Thread-Safe)하지만 상대적으로 느림.
코드 예시
public class StringBuilderExample {
public static void main(String[] args) {
// 1. 객체 생성 (가변 공간 확보)
StringBuilder sb = new StringBuilder("Java");
// 2. append(): 뒤에 내용 추가 (메모리 주소는 그대로, 내용만 바뀝니다)
sb.append(" Script");
// 현재 상태: "Java Script"
// 3. insert(): 특정 위치(4번 인덱스)에 내용 끼워 넣기
sb.insert(4, "Object");
// 현재 상태: "JavaObject Script"
// 4. delete(): 범위 삭제 (4번부터 10번 앞까지)
sb.delete(4, 10);
// 현재 상태: "Java Script"
// 5. reverse(): 문자열 전체 뒤집기
sb.reverse();
// 현재 상태: "tpircS avaJ"
// 6. toString(): 최종 결과를 불변인 String으로 변환
String finalResult = sb.toString();
System.out.println(finalResult);
}
}
3. 래퍼 클래스 (Wrapper Class)
등장 배경
자바의 기본 데이터 형식(Primitive Type)은 클래스가 아닙니다.
- 따라서 메서드를 가질 수 없습니다.
null값을 가질 수 없습니다.- 제네릭(
List불가)에서 사용할 수 없습니다.
이러한 한계를 해결하기 위해 기본 타입을 클래스로 감싼 것이 래퍼 클래스입니다.
종류
- Byte, Short, Integer, Long
- Float, Double
- Character
- Boolean
박싱과 언박싱 (Boxing & Unboxing)
박싱(Boxing)
- 기본형 데이터를 래퍼 클래스 객체로 변환하는 것.
- 오토 박싱(Auto-boxing): 자바 컴파일러가 자동으로 변환해주는 기능.
- 예:
Integer obj = 128;(내부적으로new Integer(128)처럼 동작)
언박싱(Unboxing)
- 래퍼 클래스 객체에서 기본형 데이터 값을 꺼내는 것.
- 예:
int val = obj;(내부적으로obj.intValue()호출)
[주의] 값 비교 시
- 래퍼 클래스는 객체이므로==연산자는 주소값을 비교합니다.
- 값 자체를 비교하려면.equals()를 사용해야 합니다.
- (단, Integer의 경우 -128 ~ 127 범위는 캐싱되어==비교가 가능할 수 있으나, 안전하게.equals()사용을 권장합니다.)