String Constant Pool

znftm97·2021년 12월 3일
0

JAVA

목록 보기
2/10

#String

  • String 클래스는 final로 선언되어 있다. 즉 String은 immutable(불변) 객체이다.

  • 따라서 기존 문자열에 다른 문자열을 더한다면 새로운 인스턴스가 생성된다.

  • 하지만 자바 1.5 이상부터는 String 인스턴스에 문자열을 + 할 경우 컴파일러가 StringBuilder로 변환해준다


#String 생성 방식

  1. 리터럴을 사용하는 방식

    String s1 = "JAVA";
    • heap 영역에 존재하는 String constant pool에 저장된다.
  2. new 연산자를 사용하는 방식

    String s2 = new String("JAVA");
    • heap영역에 객체가 생성되고 저장된다.

#s1 == s2는 true? false?

  • String은 래퍼타입이고 서로다른 주소값을 가르키기 때문에 false라고 생각하기 쉽다.

  • 정답은 true이다 왜일까?

  • 이유는 String Constant Pool에 대해 알아야 한다.


#String Constant Pool

  • jvm 내의 Runtime Data Area 안에 있는 heap 영역에 존재한다.
  1. 리터럴 방식으로 String을 생성하는 경우

    • String pool에서 같은 값이 존재하는지 찾고
      존재하면 String pool의 주소값을 리턴해준다.
      존재 하지않는다면 String pool에 생성한다.
  2. new 연산자로 String을 생성하는경우

    • String pool를 거치지않고 그냥 heap 영역에 생성된다.


#intern()

  • 리터럴 방식으로 String을 생성하는 경우 내부적으로 intern 메서드가 호출된다.

  • 역할은 해당 String과 동일안 객체가 String pool에 존재하면 객체의 주소값을 리턴해주고
    그렇지 않다면, 새 String 객체를 String pool에 추가하고 생성된 객체의 주소값을 리턴한다.

  • new연산자로 생성한 String객체 즉 heap영영에 있는 String 객체도 intern 메서드를 사용하면
    String pool영역으로 이동하게 된다.


#String의 equals()

  • Object equals 메서드를 오버라이딩 하였다.

  • 자바에서 문자열을 비교할 땐 equals()를 이용해야된다.
    왜일까? 내부적으로 어떤 동작과정이 이루어지는지 살펴보자

테스트 케이스

public class Main {
    public static void main(String[] args) throws IOException {
        String t1 = "test";
        String t2 = "test";
        String t3 = new String("test");
        String t4 = new String("test");

        System.out.print("t1 == t2 --> ");
        System.out.println(t1 == t2); // true
        System.out.println("t1.equals(t2) --> " + t1.equals(t2)); // true
        System.out.println("t1.equals(t3) --> " + t1.equals(t3)); // true
        System.out.println("t3.equals(t4) --> " + t3.equals(t4)); // true
    }
}

  • 모두 ture값을 출력한다. 디버깅을 해보자

equals() 메서드

디버깅

t1.equals(t2)

  • 이 경우는 같은 객체의 주소값을 가리키고 있어서
    첫 if문에서 true값을 리턴한다.
  • 같은 주소값을 가리키는 이유는 위 코드에서 이미 같은 String 값을 가지는 객체가
    Heap 영역에 있는 String pool에 생성되었기 때문에
    String t2 = "test" 시 String pool에서 같은 값을 가지는 String을 찾고
    해당 주소값을 리턴받았기 때문이다.

t1.equals(t3)

  • t1은 Spring pool 영역에, t3는 heap 영역에 존재한다.
  • 서로 다른 주소값을 가지고 있기 때문에 첫 if문을 지나 두 번째 if문을 수행한다.

  • 두 번째 if문에서는 각 한 문자씩 같은지 비교한다.
  • 모두 같기 때문에 while문을 통과하고 true를 리턴하게 된다.

t3.equals(t4)

  • t3와 t4는 new 연산자로 heap영역에 서로 다른 객체가 생성되었다.
    첫 if문에서 false를 리턴하도 두 번째 if문을 수행한다.

  • 위와 마찬가지로 한 문자씩 비교해서 true를 리턴하게 된다.
💡 결국 서로 다른 객체여도 같은 값을 가진다면 값 자체를 비교하기 때문에 true를 return하게 된다.


#정리

  • String을 생성할때는 리터럴방식으로 생성하는걸 지향하자.

  • String값을 비교할때는 ==이 아닌 equals() 메서드를 사용하자.

    • == 는 객체의 주소값을 비교, equals()는 리터럴 값 자체를 비교
profile
자기주도형 개발자

0개의 댓글