[Java] String 문자열 비교 ==와 equals()의 차이점
- Language/JAVA
- 2023. 7. 31.
String
오늘은 Java에서 가장 많이 사용하면서, String에 대해서 재밌는 이야기를 하고 넘어가려고 합니다.
String은 Java라는 언어에서 사용하는 타입 중 하나로 알려져 있습니다.
대표적으로 문자열을 담는 (객체) 타입 입니다.
그런데 여기서 String은 Value를 담는 타입 중에서 유일하게 객체를 형성하고 있습니다.
그 이유와 그 기능에 대해서 설명드리려고 합니다.
Java 문자열 비교 ==와 equals()의 차이점
우리가 String을 배울 때, 하는 말이 있습니다.
String에 들어간 'Value를 비교할 때는 반드시 equals 함수를 사용해라!'입니다.
그 이유는?
'=='는 reference의 주소값을 비교할 때 사용하는 연산자이고 equals는 reference의 값을 비교하는 함수이기 때문입니다.
Java에서 String을 배웠다면, 이 차이점 또한 배웠다고 알고 있을 것입니다.
그렇다면 '=='의 비교일 때 값은 어떻게 나올 것인가?
주소값은 과연 무엇일까?
equals() 함수와 '=='를 썼을 때, 같은 true가 나왔습니다.
여기서 한 가지 의문이 듭니다.
'주소값이 뭔지는 잘 모르겠지만, '=='는 서로 같은지 비교하는 비교연산자인데, 서로 같다고 합니다!'라고 말입니다.
그렇다면 굳이 귀찮게 왜? equals() 함수를 사용해야 하는 것일까?
Java의 String에는 String Pool이라는 영역이 존재합니다.
String Pool은 immutable(불변)이라고 불리며, 이로 인해 String은 불변의 성격을 갖고 있습니다.
String이 불변인 이유
String str = "새로운 변수";
str = "변수";
String의 불변이란?
위의 str변수에 "새로운 변수"라는 값을 삽입하였습니다.
그리고 바로 그다음줄에 "변수"라는 값을 삽입하였습니다.
만약 다음 줄에 출력하는 문장이 있다면 값은 어떻게 나올까 생각을 해보면 됩니다.
System.out.println(str);
정답은 "변수"입니다.
분명 String은 immutable(불변)이라고 했지만 str의 값은 처음 삽입한 값이 아닌, 두 번째 삽입한 결괏값이 출력되었습니다.
여기서 String값은 변했지만, 변한 것은 String객체가 아닌 또 다른 String이라는 것을 알아야 합니다.
1️⃣ String은 변수를 선언할 때, 다음과 같은 행동을 합니다.
- String객체에 담긴 Value값인 'BANANA'를 가져온다.
- String Pool에서 'BANANA'가 저장되어 있는지 확인한다.
- String Pool에 'BANANA'가 없다는 것을 확인하고, String Object를 생성한다.
- String Pool에 'BANANA'를 생성한다.
2️⃣ 만약 String Pool에 저장된 값을 가져온다면?
- String객체에 담긴 Value값인 'APPLE'를 가져온다.
- String Pool에서 'APPLE'가 저장되어 있는지 확인한다.
- String Pool에 'APPLE'이 저장된 것을 확인하고, String에 담는다.
- String에 담긴 'APPLE'은 처음에 만든 String 'APPLE'을 가져온다.
String은 Sting Pool에 값이 있는지 없는지를 확인합니다.
그리고 String은 한 번 선언된 값을 재활용합니다.
String의 비교 연산자는 s2(Value="String")와 s5(Value="String")이 동일한 true값인 것을 알 수 있습니다.
왜❓
String Pool에서 동일한 String을 불러왔기 때문에 String Object가 새로 생성되지 않고 재활용되었다는 의미를 가졌기 때문입니다.
그 근거는❓
s1의 "String"과 s4의 "String"은 서로 값은 값이지만 결과는 false입니다.
새로운 Object를 만든다고 선언을 했으며, Value는 같아도 서로 다른 Object이므로 주소값이 다르다는 것을 알 수 있습니다.
⚠️ 이 이유 때문에 String의 값을 비교할 때는 '=='을 사용하지 말아야 합니다.
따라서 String은 Value를 계속해서 가지고 있으며, immutable(불변)한다라는 것을 알 수 있습니다.
String을 immutable으로 한 이유
1. 메모리 절약
- 값이 같은 String 변수를 만약 세 개를 만든다고 과정을 해본다면, String을 선언할 때마다 새로운 저장공간(메모리)을 할당해야 합니다. 그만큼 자원 소비량이 많아지고 따라서 서버의 부담을 높아질 수 있습니다.
그러나 String Pool을 한다면, 하나의 메모리로 여러 개의 String이 마치 여러개의 값인 것처럼 사용할 수 있게 됩니다.
2. 보안
- String의 값이 외부로부터 공격을 당해서 값이 변조되는 것을 방지하기 위함입니다. Server에서 String의 값을 변조한다고 하더라도, 이미 String Pool에는 해당 값을 저장하고 있으므로 값이 변하더라도 String에 대한 주소값은 보존하고 있습니다.
3. 멀티 스레드
- Java의 장점인 멀티스레드를 할 경우, String에 선언된 값을 각각의 스레드가 공유해서 사용할 수 있습니다. 스레드의 동기화 문제를 해결하는데 String의 불변이 도움이 됩니다.
그렇다면, String의 단점은 어디 없을까?
사실, 이 글을 작성하게 된 이유가 바로 이 문제에 있었습니다.
Java로 웹 서비스를 구축하는 입장에서, String Pool은 마냥 좋은 것은 아닙니다.
이유는 간단합니다. String Pool 또한 하나의 메모리를 가지고 있으며, 이는 불변한다. 즉, 사라지지 않는 메모리라는 의미를 지니고 있습니다.
즉, Java의 장점인 GC(Garbage Collection)의 예외사항이며, 지속적인 메모리 누적이 발생할 수 있다는 의미를 지닙니다.
Java 1.7 이상에서는 Perm영역에서 Java Heap영역으로 옮겨졌고, 이는 GC(Garbage Collection)이 관리할 수 있도록!이지만, 제 주관적인 입장에서는 이 또한 개발자가 String Pool의 영역을 지우지 않는 이상은 반영구적으로 지속될 문제로 여겨졌습니다.
따라서, 이 문제에 관해서는 해결방안이 크게 없습니다.
그저 사용할 String을 최적화할 것인지, String의 대용을 찾던지입니다.
String의 장점도 있을 것이고, String의 단점 또한 존재합니다.
그렇다고 String의 단점 때문에 마냥 String을 사용 안 할 수도 없습니다.
단지, String을 사용할 때는 이 점을 주의하고 고민하고 사용해 본다면, 더 멋진 개발자가 될 것 같기에 글을 작성하고 마칩니다.
'Language > JAVA' 카테고리의 다른 글
[Java] 문자열 관리하기 (1) | 2023.11.23 |
---|---|
[Java] 데이터 타입 (1) | 2023.11.23 |
[Java] Java 음수에 대해 알아보자 (0) | 2023.07.14 |
[Java] 상속에 대해 알아보자 (0) | 2023.07.08 |
[Java] 셀레니움 설치하기 (0) | 2022.09.27 |