Programming/Java

String s = "test"와 String s = new String("test")의 차이점

String은 자바 개발자라면 자주 쓰게 되는 자료형 중 하나 이다. 해당 자료형은 불변성(Immutable) 이라는 성질을 가지고 있으며, 같은 값의 문자열에 대해서는 단 하나의 문자열 객체만을 생성하도록 설계되어 있다. 이러한 성질을 가지게 된 이유 중 하나의 가장 큰 장점은 성능 때문이다.

같은 값을 갖는 문자열 객체는 JVM의 객체가 생성되는 공간인 Heap에 매번 새로 생성하게 되면 메모리 공간적 측면에서 비효율적 이기 때문.

 

자, 다시 돌아와서

String은 두가지 생성 방식이 있고, 그에 따라 각각 차이점이 존재한다.

  1. new 연산자를 이용한 방식
  2. 리터럴을 이용한 방식

이번 포스팅은 new 연산자를 이용한 방식과, 리터럴을 이용한 방식의 차이점이 무엇인지 알아볼 것 이다.

 

public class StringTest {
    public static void main(String[] args) {
        String str1 = "test";
        String str2 = new String("test");
        
	System.out.println(str1);
        System.out.println(str2);
        
    }
}
- 결과 -
test
test

 

String s = "test"String s = new String("test") 를 각각 출력해보면, 똑같이 test 가 나온다.

 

그럼 둘은 같은 걸까?

System.out.println( str1==str2 );

 

💡 ==연산은 값을 비교하는것이 아니라 같은 메모리를 참조하는지 비교하는 것 이다.

 

해당 코드를 실행해보면, false 라는 결과를 얻게 된다.

즉, 서로 같지 않다는 뜻인건데, 어떤것이 다른지 알아보자.

 

먼저, new를 통해 생성된 String은 Heap 영역에 존재하게 된다. 반대로, 리터럴을 이용한 경우 String constant pool 영역에 존재하게 된다.

public class StringTest {
    public static void main(String[] args) {
        String str1 = "test";
        String str2 = new String("test");
        String str3 = "test";
        String str4 = new String("test");

        System.out.println(System.identityHashCode(str1));
        System.out.println(System.identityHashCode(str2));
        System.out.println(System.identityHashCode(str3));
        System.out.println(System.identityHashCode(str4));
    }
}

해당 해시코드를 출력해보는 코드를 실행해보면

460141958
1163157884
460141958
1956725890

 

이런 결과물이 나온다.

 

즉, str1, str3은 같은 해시코드를 가지고 있지만, str2와 str4는 같은 new 연산자를 이용하여 생성해주어도 다른 해시코드를 갖고있단 점을 알 수 있다.

 

String과 new String() 은 같은 값을 갖더라도 메모리 상에서 처리 되는 방식이 다르다.

두 가지 방법중 어떤 방식을 사용할지 고민이 된다면, 굳이 객체로 만들어 GC대상이 되는 것 보다 String pool을 활용 하는 방법을 사용할것이다.

두 가지 방법에 대한 메모리 효율 비교는 의미가 별로 없다. 문자열이 차지하는 메모리는 크지 않을 것 이기 때문..

 

문자열을 비교할 때에는 equals() 를 사용해주자.

 속도적인 부분이나 메모리 부분 때문에 ==을 사용해야 한다면 intern()메서드를 이용해주자.

 

💡 intern()

해당 리터럴이 pool 에 존재하는지 확인하고 존재하면 해당 pool 에 있는 리터럴을 리턴하고 없다면 리터럴을 pool 에 집어넣는다.

 

 

'Programming > Java' 카테고리의 다른 글

Class 의 개념  (0) 2021.04.29
Map.getOrDefault(Object Key, Integer defaultValue)  (2) 2021.04.18
Stack과 Queue  (4) 2021.04.13
자바 가상 머신(JVM)의 메모리 구조  (2) 2021.03.25
Java란?  (1) 2021.03.19