자바

자바 - String 객체에 대해서 알아보기

망재이 2023. 1. 10. 20:43

java에서 문자열을 표현할 수 있는 방법은 두가지가 있다.

 

1. 리터럴을 그대로 String에 저장하는 방법

String str = "abc";

2. 인스턴트 객체를 이용해 값을 저장하는 방법

String str = new String("abc");

 

두 방법에는 차이가 존재하는데 쉽게 설명하자면 1번 방법은 String Constant Pool의 "abc"값의 주소를 가져오는 것!

String에 바로 값을 설정해주면 , string pool에 속하게 되면서 그 주소값을 가져오게 됨. 그 값을 직접적으로 가져올 수 없다.

 

2번 방법처럼 String 에 인스턴스 객체를 지정해주게 되면 heap이라는 공간에 저장이 되며 그 주소값을 가져오게 됨.

 

둘은 비슷해 보이지만 전혀 다른데 둘을 비교해보면 좀 더 확실히 알 수 있다.

String str1 = "abc"; 
String str2 = new String("abc");

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

또다른 중요한 점이 있는데, String Constant Pool은 말 그대로 "Constant" Pool이라 안의 값들은 바뀔 수 없다. 

따라서 똑같은 값을 또 한번 지정해주게 되면 새로운 String 공간을 만들어내는 것이 아니라 풀 안에 있는 같은 주소값을 가지고 온다.

String str1 = "abc";
String str2 = "abc";

System.out.Println(str1 == st2); // true
//둘을 비교했을 때 같다고 나오는건 안의 값이 같아서가 아니라 주소가 같아서 true가 나오는 것!

그렇다면 직접 인스턴트 객체를 지정해줬던 값을 똑같이 새로 만들어주게 되면 어떻게 될까?

String str3 = new String("def");
String str4 = new String("def");

System.out.Println(str3 == str4); // false

메모리의 Heap영역에 새로운 공간을 만들고 새로운 주소를 가지고 오는 것이기 때문에 둘은 같지 않다. 몇 개의 같은 값을 가진 String 객체를 새로 만들어도 전부 다 다른 주소를 가지므로 전부 같지 않은 새로운 객체라고 생각하면 편하다!

 

그렇다면 주소가 아닌 값을 비교해주는 방법은 없을까?

원래 기본형의 타입을 비교할 때는 단순히 비교 연산자를 사용하면 그 '값'을 비교하는 것이지만 String은 객체이기 때문에 다른 방법으로 비교를 해줘야하는데 바로 .equals()메소드를 사용하는 것이다.

String str1 = "abc";
String str2 = "abc";

String str3 = new String("def");
String str4 = new String("def");

System.out.Println(str1 == str2); // true 같은 주소
System.out.Println(str3 == str4); // false 다른 주소
System.out.Println(str1.equals(str2)); // true 같은 값
System.out.Println(str3.equals(str4)); // true 같은 값

그렇다면 직접 값을 지정해준 String 객체와 인스턴트 객체를 지정해준 String 객체끼리 비교는 어떻게 할 수 있을까?

그럴 때는 .intern();메소드를 이용해주면 된다. intern()은 새 문자열의 값을 스트링 풀로 넣어서 그 주소를 비교한다고 생각하면 된다.

String str5 = "Hello";
String str6 = new String("Hello");

System.out.Println(c == str6.intern()); 
// str6의 "Hello"를 스트링 풀로 집어넣어서 그 주소를 가지고 온다고 생각하면 됨

 

※ 정리! 

// String 객체에 들어있는 문자열의 값이 바뀌면, String 값이 가리키는 주소도 바뀐다.

// String 객체에 들어있는 문자열 같은 값으로 재할당해도 String 값이 가리키는 주소는 바뀌지 않는다.

// 문자열을 어딘가에 저장해놓고 관리하고 있구나!

// 내가 한번 썼던 문자열들을 저장해놓은 저장소 ==> 스트링풀 

728x90