공부하는 스누피
[JAVA] String Class 본문
자바에서 문자열은 String 객체를 클래스로 명시해야 한다. 정수나 실수, 그리고 문자(char)도 primitive type에 포함되는데 왜 문자열은 primitive type에 포함되지 않는지부터 알아보자.
자바에서 primitive type은 공간을 효율적으로 쓰게 해 준다. 데이터 타입별로 값의 크기가 일정하기 때문이다. int형은 -2^32 ~ 2^32-1의 범위 안에서만 표현 가능하고, char형은 16비트에서만 표현할 수 있게 정해 둔다. 이렇게 값의 크기에 제한을 두면 메모리 상에 저장할 공간을 지정할 때 훨씬 쉬워진다. 더 이상 값의 크기가 변경되지 않으니 Stack 영역에 벽돌처럼 차곡차곡 쌓을 수 있을 것이다 (데이터를 효율적으로 보관할 수 있다).
하지만 크기가 변화무쌍한 데이터 타입은 primitive type처럼 표현하기 어렵다. 그래서 가변 영역인 Heap 영역에 데이터를 저장하고, Stack 영역에는 데이터가 저장된 곳을 가리키는 Reference를 저장한다 (Reference: 포인터와 비슷하지만 실제 메모리 주소를 의미하지 않음). 이러한 데이터 타입을 Reference Type이라고 통칭하는데, String도 이중 하나이다.
String은 자주 쓰이기 때문에 다른 클래스 기반의 Reference Type과는 다르다.
우선, Heap 영역에 문자열만 저장되는 String Constant Pool(literal pool)이 있다. 우리가 "자바"라는 문자열 객체를 하나 생성하면, String Constant Pool에는 "자바"가 등록된다. Pool에 등록된 문자열의 위치를 문자열 객체 인스턴스가 저장하는 방식이다. String type 변수는 문자열 객체 인스턴스를 가리키고, 문자열 객체 인스턴스는 Pool에 있는 문자열의 위치를 가리킨다.
// String 객체 생성. s1은 String 객체 데이터의 위치를 가리킨다.
// String 객체는 String Constant Pool의 "안녕"을 가리킨다.
String s1 = new String("안녕");
다른 특징으로는 생성자 없이 객체 생성이 가능하다는 점이다. 생성자 없이 다른 primitive type처럼 변수에 값을 할당하기만 해도 되는데, 이때 변수에는 String Constant Pool에서 해당 문자열의 위치가 바로 저장된다. String 객체를 생성하면 객체 인스턴스를 거쳐야 Pool에 접근할 수 있는 것과 다르다.
// String Constant Pool에서 해당 문자열의 위치를 바로 저장한다.
String s2 = "스누피"; // dkdie001
// 그래서 같은 문자열을 가리키는 s3도 s2와 같은 주소값을 가지고 있다.
String s3 = "스누피"; // dkdie001
// 하지만 String 객체를 만들면 객체 인스턴스의 주소값을 가지고 있어 다르다.
String s4 = new String("스누피"); // String@aldkfjf
자바에서 문자열은 Immutable(불변)하다. 그 이유는 String Constant Pool과 관련이 있다. "스누피"라는 문자열이 들어간 변수를 하나 만들면, "스누피"는 Pool에 들어간다. 여기서 "스누피"가 들어간 변수를 하나 더 만들어도 Pool에 "스누피"가 더 생기지 않는다. 이미 Pool에 "스누피"가 있어 그 주소를 가리키게 된다.
문자열을 가공할 때 많이 쓰이는 방법 중 하나가 덧셈 연산자를 사용한 방법이다. 방금 만든 "스누피"에 "공부"를 +로 붙이면 Pool에 있는 "스누피"는 변하지 않는다. "스누피공부"라는 새로운 문자열이 Pool에 추가되고 "스누피"는 GC가 일어날 때까지 Pool에 남아 있는다. 그래서 반복문을 사용해 문자열을 +로 붙여가면서 만들고자 할 때 Pool의 공간이 낭비된다. 그 대신 StringBuilder나 StringBuffer를 사용하는 것이 좋다.
String의 개념을 한번 정리해보고자 조금 장황하게 풀어서 설명해봤다.
요약하자면 String Class는 문자열을 위한 클래스로, 변수 선언하는데 두 가지 방법이 있다. 두 가지 방법 모두 결과적으로 문자열이 String Constant Pool에 저장되게 하지만 new 키워드로 선언할 경우 변수는 객체 인스턴스 주소값을 가리키고, 바로 문자열을 변수에 대입할 경우 Pool에서의 주소가 바로 저장된다는 점에서 차이가 있다.
'Languages > Java' 카테고리의 다른 글
[디자인 패턴] 자바의 싱글턴(Singleton) (0) | 2021.02.16 |
---|---|
[디자인 패턴] 정적 팩터리 메서드 (static factory method) (0) | 2021.02.15 |
[JAVA] OOP 특징 (0) | 2021.02.07 |
[JAVA] Type casting (0) | 2021.01.13 |
[JAVA] HashMap 사용법 정리 (0) | 2020.07.10 |