java - string

sun·2024년 2월 23일
0

java

목록 보기
27/38

Java에서 String은 굉장히 자주 사용되며, 두 가지 생성 방식이 있다.

new 연산자를 이용한 방식
리터럴을 이용한 방식
이 두 가지 방식에는 큰 차이점이 존재한다.

new를 통해 String 객체를 생성하면 Heap 영역에 존재하게 된다.

리터럴을 이용할 경우, String Constant Pool이라는 영역에 존재하게 된다.

public class StringMemory{
  public static void main(String[] args){
    String literal = "loper";
    String object = new String("loper");
    
    literal == object; // false
    literal.equals(object); // true
  }
}

== 연산의 결과는 false이다.

== 연산자는 객체의 주소값을 비교하기 때문에 일반 객체처럼 Heap 영역에 생성된 String 객체와 리터럴을 이용해 String Constant Pool에 저장된 String 객체의 주소값은 다를 수 밖에 없다.

equals() 메소드의 수행 결과는 true이다.

이는 문자열 내용을 비교하기 때문에 같은 문자열에 대해서 true를 반환하는 것이 맞다.

왜 이런 결과가 나올까?
이를 위해서는 동작 방식에 대한 이해가 필요하다. String을 리터럴로 선언할 경우, 내부적으로 String의 intern()이라는 메소드가 호출되게 된다.

intern() :

주어진 문자열이 String Constant Pool에 존재하는지 검색하고 있다면 그 주소값을 반환하고 없다면 String Constant Pool에 넣고 새로운 주소값을 반환하게 된다.

public class StringMemoryInternTest{
  public static void main(Strig[] args){
    String literal = "loper";
    String object = new String("loper");
    String intern = object.intern(); // 명시적으로 호출. 
    
    literal == object; // false
    literal.equals(object); // true
    
    literal == intern; // true
    literal.equals(intern); // true
  }
}

기존에 new를 통해 생성된 String 객체와 리터럴로 생성된 String 객체를 == 연산하였을 경우, false를 반환했지만 new를 통해 생성된 String 객체의 intern() 메소드를 호출하여 새로운 String 객체인 intern에 대입할 경우, 리터럴로 생성된 String 객체와 == 연산시 true를 반환하게 된다.

Oracle엔지니어들이 java7에서 Perm영역이 아닌 Heap영역으로 String Contant Pool의 위치를 변경했다.
Heap 영역으로 변경함으로써 얻는 이점은 무엇일까?

->바로 String Contant Pool의 모든 문자열도 GC 'Garbage Collection(가비지 컬렉션)'의 대상이 될 수 있다는 점이다.

0개의 댓글