본문 바로가기
Java/정리

[java] String의 메모리 저장 방식

by 콧등치기국수 2021. 10. 14.

오늘 치과를 갔는데 20~30분 기다려야한다고 해서 되게 간단한 코딩테스트를 풀었다.

금방 풀고 다른 분 풀이를 보며 모르는 걸 검색하다가 우연히 string의 메모리 저장방식에 대한 글을봤다.

예전에 이 부분을 공부했었는데 꽤 잊어버려서 내 블로그에 예전 글들도 다시보고 다른 블로그 글도 보면서 공부했다. 

 

1. String 객체 메모리 할당

String은 참조 자료형이므로 stack영역에 참조값(heap메모리에 저장된 주소값)을 저장하고,

heap영역에는 참조값이 가리키는 데이터값이 저장된다.

//string, 메모리구조
String[] a = null;
System.out.println(a);    // null  ->stack영역 공간 할당
		
a = new String[] {"안녕"}; // Heap 영역에 공간 할당,
        		  // 변수 a에 참조값 할당
System.out.println(a);    // [Ljava.lang.String;@15db9742  ->heap영역의 참조값

처음에 String[]객체 a를 new 생성자 없이 null로 선언하면 stack영역 공간만 할당되어서

변수 a를 출력하면 null값이 출력된다.

 

그후 new 연산자로 생성해주면 heap영역에 공간이 할당되어서 변수 a에 참조값이 할당된다.

따라서 마지막으로 변수 a를 출력한 경우에 null이 아닌 heap영역의 참조값(주소값)이 출력된다.

 


자바에서 문자열(String)은 2가지 방법으로 생성이 가능하다. 첫 번째는 생성자인 new 연산자를 이용한 문자열 생성 방식이고, 두 번째는 문자열 리터럴 생성 방식인데, 겉으로 보았을 때의 문법 차이도 있지만 실제 메모리에 할당되는 영역에도 차이가 있다. 

 

 

2. new 연산자를 이용한 문자열 생성 방식

new연산자를 이용하여 문자열을 생성할 경우, 값이 동일한지 상관없이 heap영역에 인스턴스가 생성된다.

아래에서 b1 과 b2는 "hi"라는 같은 값을 가지지만 new 연산자를 이용해 생성했으므로 heap영역에 각각 인스턴스가 생성되기 때문에 b1과 b2가 참조하는 주소값을 다르다. 따라서 '=='으로 비교했을때 주소값이 다르므로 "다른 주소값 입니다."가 출력된다.

//2. String new연산자 -> 주소값 비교(==)
//		            -> heap 영역
String b1 = new String("hi");
String b2 = new String("hi");
		
System.out.println(b1);
System.out.println(b2);
		
if(b1 == b2){
	System.out.println("같은 주소값 입니다.");
}else{
	System.out.println("다른 주소값 입니다.");
}

 

3. 문자열 리터럴 생성 방식

new연산자가 아닌 리터럴 방식으로 문자열을 생성할 경우 heap메모리안의 String Constant Pool에 값을 저장한다.

c1객체를 생성할 때 String Constant Pool에 "hi"가 저장된다. 그 후 c2에서 또 "hi"를 저장하려하면 new연산자와 달리 인스턴스를 새로 생성하지 않고, 앞서 만들어둔 인스턴스의 주소값을 참조한다.

즉 String Constant Pool에 "hi"하나만 저장이 되고, c1과 c2는 같은 주소를 참조한다. 

따라서 아래 실행결과는 "같은 주소값 입니다." 가 출력된다.

// 3. String 리터럴 생성-> 주소값 비교(==)
//		        -> String Constant Pool
String c1 = "hi";
String c2 = "hi";

System.out.println(c1);
System.out.println(c2);

if (c1 == c2) {
	System.out.println("같은 주소값 입니다.");
} else {
	System.out.println("다른 주소값 입니다.");
}

 

아래 사진은 위 개념들을 그림으로 나타낸 것이다. 다른 분의 블로그에 있는 걸 가져와서 변수값은 달랐지만 이해하기에는 매우 좋았다.

출처 : https://dydtjr1128.github.io/java/2019/04/23/JAVA-String.html

 

 

 

 

 

참고 및 출처: https://ict-nroo.tistory.com/18

                  https://madplay.github.io/post/java-string-literal-vs-string-object