[Java] 문자열 리터럴과 객체

calis_ws·2024년 2월 3일
0

literal

변수에 저장되기 전의 값을 리터럴이라고 한다.

int score = 100;		// 변수 : score
final int MAX = 100;	// 상수 : MAX

선언 방법

자바에는 String 을 선언하는 방법이 리터럴과 객체로 선언할 수 있다.

//리터럴
String a = "hello";
String b = "hello";

//객체
String c = new String("hello");
String d = new String("hello");

System.out.println(a.equals(b)); 	// true
System.out.println(a == b); 	 	// true

System.out.println(c.equals(d)); 	// true
System.out.println(c == d); 		// false

System.out.println(a.equals(c)); 	// true
System.out.println(a == c);			// false

리터럴 선언 방식은 Heap 영역 안에 있는 String Constant Pool(상수풀) 에 위치한다.
String Constant Pool 에 이미 존재하는 문자열이라면 같은 주소값을 공유한다.

따라서 변수 a, b 는 비교하였을 때, 문자열과 주소값이 모두 같은 것을 확인할 수 있다.

String Constant Pool 이란

자바 메모리 중 Heap 영역 안에 위치하여 String 을 별도로 관리하는 장소다.
Heap 안에 있기 때문에 모든 스레드가 공유할 수 있고 가비지 콜렉터의 대상이 된다.

객체 선언 방식은 Heap 영역에 할당된다.
새로운 인스턴스를 생성할 때마다 Heap 영역에 객체가 새로 생긴다.

따라서 변수 c, d 를 비교하였을 때 문자열은 같지만 Heap 영역에서 서로 다른 객체로 생성되었기 때문에 주소값은 다르다.

문자열 리터럴은 String Constant Pool 영역에, 객체는 Heap 영역안에 위치하므로
변수 a, c 는 서로 다른 주소값을 참조한다.

System.out.println(a == c.intern()); 	//true

intern() 메서드는 String Constant pool 에서 리터럴 문자열이 있으면 반환하고, 없다면 새로 문자열을 넣어주고 그 주소값을 반환한다.

new 연산자로 생성한 변수 c 에 intern() 메서드를 적용하면 리터럴 변수인 a 와 참조하는 주소값이 같아진다.

  1. intern() 메소드 실행
  2. String Constant Pool 에 문자열 존재하는지 확인
  3. 동일한 주소값 리턴

정리

리터럴

  • 상수풀이라는 특별한 메모리 영역에 저장된다.

  • 서로 같은 문자열 리터럴을 사용하는 경우, 동일한 객체로 인식된다.

  • == 연산자를 사용하여 동등성을 비교할 수 있다.

  • 자바는 상수풀에서 중복된 문자열을 관리하므로 같은 문자열 리터럴을 사용하면 같은 객체를 참조하게 된다.

객체

  • new 연산자로 문자열을 생성하면 새로운 객체가 heap 메모리에 할당된다.

  • 동일한 문자열이라도 별도의 객체로 취급된다.

  • 불필요한 메모리 사용이 발생할 수 있다.

  • == 로 동등성을 비교하면 객체의 참조값을 비교하게 되므로 equals() 를 사용하여 내용을 비교해야 한다.

일반적으로 문자열을 다룰 때는 리터럴 방식을 사용하는 것이 권장되며, 이는 코드의 가독성을 높이고 불필요한 메모리 사용을 최소화할 수 있다.

출처

https://velog.io/@kiiiyeon/자바-스트링-객체-생성-방법

profile
반갑습니다람지

0개의 댓글