본문 바로가기

Java

String에 대해서


다음의 코드를 보겠습니다~


public class Test {
 public static void main(String[] args) {
  String a = "123";
  String b = "123";
  String a1 = new String("123");
  String b1 = new String("123");
  String a2 = String.valueOf("123");
  String b2 = String.valueOf("123");
  String a3 = "1"+"2"+"3";
  String b3 = "123";
  System.out.println(a==b);
  System.out.println(a1==b1);
  System.out.println(a2==b2);
  System.out.println(a3==b3);
 }
}

실행하면 답이 어떻게 나올까요?

true
false
true
true
입니다.

하나하나 보겠습니다.

첫번째의 경우 ""로 String 인스턴스를 생성하는 경우에는 이것을 jvm이 String pool에 등록을 해 놓고
같은 값을 생성하려 할 경우 이 pool을 뒤져서 같은 객체를 리턴하게 됩니다. 따라서 a와 b가 같은 곳을 참조하게 되기 때문에 true가 됩니다.

두번째의 경우에는 new String으로 객체를 생성하는 경우 jvm의 String pool을 이용하지 않고
바로 메모리에 객체를 생성시킵니다. 따라서, a1과 b1은 서로 다른 객체를 참조하게 되고 따라서 false가 됩니다.

세번째의 경우에는 String.valueOf의 메서드를 보게 되면
    public static String valueOf(Object obj) {
      return (obj == null) ? "null" : obj.toString();
    }

이렇게 구현이 되어있습니다. 즉 String.valueOf("123")은
"123".toString()이 되는 것입니다. toString 메서드는 return this; 입니다.
즉 "123" 자체를 리턴하게 되고 이 "123"은 pool에 등록이 되어 있으므로 a2와 b2는 같은 객체를 참조하고 있게 되는 것입니다.

그렇다면 여기서 잠깐?
"123"이 pool에 등록되어 있다고 한다면 위의 경우에서
System.out.println(a==b2);
도 true를 리턴하지 않을까? 라고 생각 할 수 있겠죠?

맞습니다. 위의 경우에도 true를 리턴합니다.

마지막의 경우에 String을 + 연결하는 경우에도 jvm String pool에 등록이 됩니다.
다만, String은 불변객체이기 때문에 jvm의 String pool에 단순히
"123"만 들어가는 것이 아니라 "1", "12" 도 등록이 되게 됩니다. 물론 참조하고 있는 변수는 없겠지만요.(즉 GC의 대상이 됩니다. 그래서 String을 +로 붙이는 것이 좋지 않게 됩니다. 메모리를 낭비하게 되거든요)

String이 불변객체이기 때문에 StringBuffer 의 append 처럼 이미 생성된 객체의 값을 늘려가는 것이 아니라 +로 붙여낼때 마다 매번 새로운 객체를 생성하게 되기 때문입니다.

#JDK 1.5 버젼 부터는 위의 경우에 StringBuilder를 사용해서 객체를 생성하도록 한다고 합니다. 모든 경우에 그렇게 변환되는지는 잘 모르겠습니다.

그럼 역시 마찬가지로
System.out.println(a==a3); 이것도 true를 리턴 할까요?

네~ 마찬가지로 true를 리턴합니다.

http://iilii.egloos.com/4427484 이 포스트로 공부하고 제가 다시 정리해본 내용입니다. ^^