티스토리 뷰

자바에서 String 클래스를 사용하면서 하나의 의문점이 생겨서 이 글에 정리해보도록 한다. 보통 초기화를 할 때 두 가지 방법이 존재한다. 직접 문자열 상수를 넣거나, new 연산자를 이용하여 사용하는 것이다. 그 형태는 아래와 같다.


String s = "Hello World!";

String s = new String("Hello World!");


위 문법을 적용시킨 코드를 통해 자세히 알아보도록 하자.



<코드>

public class StringTest {

	public static void main(String[] args) {
		String s1 = "Hello World!";
		String s2 = new String("Hello World!");
		
		System.out.println(s1);
		System.out.println(s2);
	}

}


<결과>

Hello World!
Hello World!



위 코드에서 s1과 s2를 다른 방식으로 초기화 시켰다. 초기화 방법을 다르게 한다고 해서 결과값이 다르지는 않다는 것을 알 수 있다. 그렇다면 저 코드는 완벽히 동일하다고 할 수 있을까?


먼저 이 두 코드의 차이점을 이해하기 위해서는 Heap Area와 그 안에 존재하는 String Constant Pool에 대해 알고 넘어갈 필요가 있다. 아래 그림을 통해 알아보도록 하자.





먼저 Heap Area에는 문자열 객체 뿐만아니라 모든 객체들이 생성되는 메모리 공간이다. 그리고 그 메모리 공간의 일부는 String Constant Pool이라고 불리는 문자열 상수가 저장되는 메모리 공간이 존재한다.


우리가 문자열을 사용하는 대부분의 경우는 문자열을 직접 수정하고 고치는 경우와 단순하게 저장된 문자열을 읽어서 출력하는 경우이다. 여기서 문자열을 읽는 전용으로 사용한다면 String Constant Pool에 선언하는 것이 더 유용하다고 할 수 있고, 같은 문자열이라도 각각을 따로 다룰 필요가 있다면 그 문자열은 Heap Area에 선언하는 것이 바람직하다고 할 수 있다. 왜 그런지는 다음 코드를 통해 알아보도록 하자.


혹시 Heap Area에 대해서 알고싶다면 아래의 링크를 참조하길 바란다.


[Java]JVM Memory Structure

http://hyoje420.tistory.com/2?category=292579




String s = "Hello World!";



위와 같이 초기화 했을때는 각 객체가 참조하는 값이 같은지 다른지를 확연하게 보여주는 코드이다.



<코드>

public class StringTest {

	public static void main(String[] args) {
		String s1 = "Hello World!";
		String s2 = "Hello World!";
		
		if(s1 == s2)
			System.out.println("참조하는 값이 같습니다.");
		else
			System.out.println("참조하는 값이 다릅니다.");
	}

}


<결과>

참조하는 값이 같습니다.



s1과 s2가 참조하는 객체가 동일한지 확인하기 위해서 '=='연산자를 이용하여 확인해 보았다. 결과는 두 참조변수가 같은 객체를 바라보고 있는 것으로 나타났다.


결국 String s1 = "Hello World"라는 코드를 실행하게 되면 String Constant Pool에 문자열 상수가 생성되고, 다음에 s2가 s1와 같은 문자열 상수로 초기화 되면 객체를 생성하지 않고 이미 존재하는 String Constant Pool의 객체를 참조하는 형식으로 동작한다는 결론이다. 아래에 이해를 돕기위한 그림을 그려보았다.





위 그림과 같이 하나의 객체를 두 참조변수가 참조하는 형태로 동작한다.




String s = new String("Hello World!");



위와같이 생성하면 참조하는 값이 어떻게 나오는지 확인해보자.



<코드>

public class StringTest {

	public static void main(String[] args) {
		String s1 = new String("Hello World!");
		String s2 = new String("Hello World!");
		
		if(s1 == s2)
			System.out.println("참조하는 값이 같습니다.");
		else
			System.out.println("참조하는 값이 다릅니다.");
	}

}


<결과>

참조하는 값이 다릅니다.



위에서의 결과와는 다른 모습을 보여준다. 각 참조변수 s1, s2가 참조하는 객체가 다르다는 결과를 보여준다. 따라서 new 연산자로 객체를 생성하여 문자열을 초기화한다면, 초기화 할때 객체를 생성하여 그 객체를 참조하도록 동작한다는 것을 확인할 수 있다. 아래 그림을 통해 이해를 도울 수 있을 것이다.





각 참조변수는 Heap Area에 별도로 생성된 문자열 객체를 참조하는 것을 볼 수 있다.




String s = "" vs String s = new String("");



위의 두 방식 중 어느것이 더 좋다고 단정지을 수는 없다. 하지만 어떤 상황에서 어떤 것이 더 좋을 지는 설명할 수 있겠다.


필요한 문자열을 생성해 놓고 읽는 경우에만 사용할경우에는 String Constant Pool에 생성하고 사용하는 것이 좋을 것이다. 왜냐하면 같은 문자열을 new 연산자로 반복적으로 생성한다면 이것은 메모리의 낭비로 이어질 수 있기 때문이다.


따라서 상황별로 알맞게 객체를 생성해 주는 것이 바람직 한 것으로 보인다.




참고



뇌를 자극하는 Java 프로그래밍 - 김윤명

http://ict-nroo.tistory.com/18

http://tomining.tistory.com/195

https://hashcode.co.kr/questions/857/%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-string%EA%B0%9D%EC%B2%B4%EC%99%80-%EB%AC%B8%EC%9E%90%EC%97%B4-string%EC%9D%98-%EC%B0%A8%EC%9D%B4%EA%B0%80-%EB%AD%94%EA%B0%80%EC%9A%94

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함