느리더라도 꾸준히

[String]String 선언 방식 비교 본문

Java

[String]String 선언 방식 비교

테디규 2022. 10. 31. 16:55

목표

  1. String 선언 방식을 비교한다.
  2. 왜 선언 방식을 두가지나 만들어 놓았을까?

본문

String 변수는 아래 두가지 방식으로 값을 할당할 수 있다.

// 1번
String str1 = "steadykyu";
String otherStr1 = "steadykyu";

// 2번
String str2 = new String("steadykyu");
String otherStr2 = new String("steadykyu");

위 자료에 의하면 두 방식은 아래와 같은 차이를 가진다.

str1==otherStr1        // true
str2==otherStr2        // false

str1, otherStr1는 문자열의 참조값을 공유하기에 true가 생성된다.

str2, otherStr2는 서로 다른 인스턴스의 주소값을 비교하므로, false가 생성된다.

이때 str2, otherStr2는 서로 다른 주소값에서 값을 참조해온다. 그렇다면 str1과 otherStr1은 어디에 저장되어 리터럴 값을 참조해오는 것일까?

Heap 영역의 String pool

일반적으로 참조형 객체값들은 Heap영역에 저장되어 있는데, 이 Heap 영역에는 String pool이라는 영역이 존재한다.

먼저 str1에 literal로 선언시 String pool에 "steadykyu"객체값이 들어가게 되고, 이때의 주소값(A라고 가정)은 str1에 저장한다.(정확히는 참조변수 str1이 주소값이므로, stack영역에서 저장한다.)

이후 otherStr1에서 다시 literal로 "steadykyu"를 할당하라고 하면, String pool에 "steadykyu" 객체값이 있으므로 otherStr1에 주소값(A)를 저장한다.

그러므로 str1과 otherStr1은 같은 주소값을 가지게 된다.

왜 사용할까?

Java 디자이너는 모든 종류의 Java 어플리케이션에서 가장 많이 사용되는 데이터 타입이 String이 될 것이라고 예측했었다. 즉 String 타입의 객체들이 가장 많은 메모리를 차지할 것을 알고 있었기 때문에, 처음부터 최적화의 필요성을 고려했던 것이다.

그래서 선택된 방법이 String Pool에 리터럴을 포함한 String 객체를 공유하고,  같은 리터럴로 생성되는 String 객체를 줄여버리는 것이었다. 그리고 String Pool 속의  String 클래스를 immutable(불변) 하게 만들어 공유를 해도 문제가 발생하지 않게 만들었다.

for(int i = 0; i < 500; i++) {
    String str = "Hello World";
    System.out.println(str);
}

String의 불변성이 없어서 객체를 공유할수 없다면 어떻게 될까?

String Pool을 통한 String 객체를 공유할 수 없게 되고, 위 코드는 "Hello World"라는 500개의 String 객체를 생성하게 된다. 엄청난 메모리 낭비를 일으킨다.

하지만 실제로는 불변의 성질을 갖기 때문에 실제로 "Hello World"라는 문자열 객체는 Heap 영역속 String Pool에 단 하나만 생성되어 공유될수 있는 것이다.

이러한 기능을 String 객체의 캐싱 기능부르고,  아래 장점들을 가지고 있다.

  1. 메모리 절약
  2. 속도가 향상되는 효과
    • 존재하는 String을 객체생성이 아닌 String Pool에서 가져오기 때문입니다.

출처

https://wildeveloperetrain.tistory.com/34

Comments