자바 String, literal pool 및 특성

자바 String, literal pool 및 특성

원래 기록을 잘 안하긴 하는데 이 내용은

두고 두고 설명 하고, 알고 있으면 좋을 내용인 듯

하여 기억 보단 기록을 한 번 진행하려고 한다.

일단 자바에서 String 굉장히 특이한 친구이다.

분명 클래스인데도 불구 하고, 일반 변수 처럼

값을 대입해 사용할 수 있다.

이게 무슨 말이냐 하면

String str1 = "apple"; // 1 String str2 = new String("apple")'; // 2

둘 다 가능 하다는 것이다. 하지만 이게

보기엔 둘 다 String 객체를 생성하는 듯 하여도

내부적으로는 완전히 다른 메커니즘을 가지고

동작하게 된다.

1번의 경우 메모리에 상수와 String 문자열을

저장하는 literal pool 이라는 곳에 해당 문자열이

저장 되게 된다.

2번의 경우 new 연산자를 통해 객체를 생성한 것임으로

힙 영역에 객체를 생성 하게 된다.

그리고 만약에

String str1 = "apple"; String str2 = "apple";

이렇게 같은 문자열을 저장하게 되면 literal pool 에

저장된 문자열의 경우 중복을 허용 하지 않고,

하나의 "apple" 문자열을 가르키게 된다.

그렇기 때문에 str1 == str2 를 해도 true 가 나오게 된다.

같은 하나의 문자열을 가르키고 있기 때문에

당연히 메모리 주소도 같은 것이다.

String str1 = new String("apple"); String str2 = new String("apple");

위의 경우 힙 영역에 저장되게 되는데

각각 동적할당을 통해 메모리 영역을

할당 받아 저장된다. 그렇기 때문에

str1 == str2를 하더라도 false 값이 나오게 된다.

문자열은 같더라도 각각 다른 객체를

가르키고 있고, 각각 다른 메모리 주소를

비교하기 때문이다.

해서 String 의 경우 대부분 첫 번째 방식

String str1 = "apple"; 방식으로 객체를 생성한다.

이렇게 생성하면 이점이 또 있는데 바로

불변성을 가지게 된다는 것이다 .

어찌 보면 당연한 사실이다. 만약 같은 문자열을

가르키고 있는 String 객체 두 개가 있다고 가정해보자.

만약 둘 중 하나가 다른 문자열 객체를 할당 받게 된다면

이는 가르키고 있는 문자열이 바뀌는 것이 아니라

새로운 문자열이 literal pool 에 생성되고,

이를 가르키게 된다. 그래야만 다른 하나가 피해 보지 않고

정상적으로 다른 값을 가르킬 수 있게 되는 것이다.

이런 이유에서 String 문자열은 불변성을 가지게 된다.

그리고 이런 이유에서 오는 특징 중 하나는

'+' 연산 시 문자열이 더해지면서 바뀌는 것이 아닌,

대체 되는 것이 아닌 계속해서 새로 생성되는 것이다.

만약 이런 코드가 있다고 생각해보자

public class Test { public static void main(String[] args) { String sum = ""; for (char c = 'A'; c < 'z'; c++) { sum += c; System.out.println(sum); } } }

결과는 이런 결과를 가진다.

이 때 생성되는 문자열들은 맨 처음 문자열이

대체 되면서 생성 되는 것이 아닌 메모리에

모든 문자열이 계속 생성된다는 것이다.

물론 GC 에 의해 가장 마지막 문자열이 아닌

이전의 문자열들은 어느 순간에는 메모리에서

내려 가겠지만 그 순간이 언젠지는 제임스 고슬링도

모른다고 한다.

즉 참조변수 sum 이 가르키는 문자열은 계속 바뀌지만

'+' 연산자로 인해 생성된 문자열들은 메모리에 남는다는 것이다.

대체 하지 않고, 새로 만들기 때문

오늘은 이정도로 정리 하면 될 듯 하다.

from http://win-fly.tistory.com/2 by ccl(A) rewrite - 2021-09-17 21:28:06