
자바에서 가장 많이 하는 실수 중 하나가 바로 String 비교다.
왜 ==를 쓰면 안 되는지, 왜 equals()를 써야 하는지 헷갈린 적 있지?
그 이유는 바로 "메모리 구조"와 관련 있다.
자바는 "abc"처럼 리터럴로 선언한 String을 JVM 내부 String Pool에 저장한다.
같은 리터럴이 나오면 새로 만들지 않고 기존 Pool의 값을 재사용한다.
String strA = "abc";
String strC = "abc";
System.out.println(strA == strC); // true
✔️ 둘 다 "abc"라는 같은 리터럴이기 때문에 같은 주소를 가리킨다.
new String()을 쓰면 Heap 메모리에 새로운 객체를 무조건 생성한다.
Pool에 같은 값이 있어도 상관없이 새로 만들어서 다른 주소를 가진다.
String strA = "abc";
String strB = new String("abc");
System.out.println(strA == strB); // false
✔️ 값은 같아도 메모리 주소가 다르기 때문!
String strA = "abc";
String strB = new String("abc");
String strC = "abc";
String strD = new String("abc");
System.out.println(strA == strB); // false (리터럴 vs new 객체)
System.out.println(strA == strC); // true (같은 리터럴 → 같은 주소)
System.out.println(strB == strD); // false (new 객체끼리는 서로 다른 주소)

"abc" 리터럴 → String Pool에 1개만 생성
new String("abc") → Heap 메모리에 각각 따로 생성
== 말고 반드시 equals() 써라| 비교 방법 | 설명 | 결과 |
|---|---|---|
== | 주소 비교 (레퍼런스 비교) | 같아도 false 가능 |
equals() | 실제 문자열 값 비교 | 값이 같으면 무조건 true |
System.out.println(strA.equals(strB)); // ✅ true (값 비교)
"abc"처럼 리터럴은 String Pool 공유
new String("abc")는 Heap에 새로 생성
String 비교는 무조건equals()로!
아래 코드를 실행했을 때 출력 결과는?
String str1 = "hello";
String str2 = new String("hello");
String str3 = "hello";
System.out.println(str1 == str2); // ?
System.out.println(str1 == str3); // ?
System.out.println(str1.equals(str2)); // ?
✍️ 정답
🙅♀️ str1 == str2 → false
"hello"는 String Pool, new String("hello")는 Heap에서 따로 생성
주소가 다르다!
🙆♀️ str1 == str3 → true
둘 다 리터럴 "hello" → String Pool에서 같은 주소
🙆♀️ str1.equals(str2) → true
값 비교니까 "hello" == "hello" → true