자바로 문제를 풀다가 문자열을 비교해야 하는 상황이 있었습니다.
비교 연산자를 사용해야겠다는 생각에 무의식적으로 ==
연산자를 사용하였더니 원하던 결과값을 얻을 수 없었습니다.
그제서야 문자열을 비교하는 상황에서는 equals()
메소드를 사용해야 한다는 걸 떠올렸습니다.
하지만, equals()
를 사용해야 한다는 것만 알고 있었지
왜 사용해야 하는 지에 대해서는 모르고 있었습니다.
그래서 자료들을 찾아보았고, 정리를 해보았습니다.
먼저, String 변수를 생성하는 과정을 살펴봅시다.
일반적으로 String 변수를 생성하는 방법에는 두 가지가 있습니다.
- 리터럴을 이용한 방식
new
연산자를 이용한 방식
리터럴 방식으로 String 변수를 생성하는 방법은 다음과 같습니다.
String str = "Chill guy";
이 방식으로 생성된 문자열은 JVM의 String Pool
에 저장됩니다.
그리고 내부적으로 intern()
라는 메서드가 호출됩니다.
주어진 문자열이 String Pool
에 존재한다면 그 주소값을 반환하고, 존재하지 않는다면 String Pool
에 입력 후 새로운 주소값을 반환합니다.
new
연산자를 사용해 String 변수를 생성하는 방법은 다음과 같습니다.
String str = new String("Chill guy");
이 방식을 통해 문자열을 생성하면, 리터럴 방식과는 다르게 Heap 메모리에 변수가 저장됩니다.
예를 들어 코드를 이렇게 작성했다고 가정해봅시다.
String a = "Chill";
String b = "Chill";
String c = new String("Chill");
String d = new String("Chill");
a
와 b
는 리터럴 방식으로,
c
와 d
는 new 연산자를 사용하였습니다.
a
는 String Pool 영역에 "Chill"이라는 문자열이 존재하지 않기 때문에, 새로 생성이 됩니다.
하지만 b
를 선언할 때에는, String Pool에 "Chill"이라는 문자열이 이미 존재하지 때문에 그 주소값을 가지게 됩니다.
즉 a
와 b
는 같은 주소값을 갖게 되는 것이죠.
그리고 c
와 d
는 new 연산자 방식으로 생성했기 때문에, Heap 영역 안에서 서로 독립적인 주소값을 가지게 됩니다.
그림으로 표현하면 아래와 같습니다.
앞서 살펴보았듯이, 문자열 변수의 생성 방식에 따라 서로 같은 주소값을 가지는 경우와 다른 주소값을 가지는 경우가 존재합니다.
위의 그림에서 데이터 값은 a
, b
, c
, d
모두 "Chill"로 같을 수 있지만, 주소값을 비교해본다면 a
와 b
는 같은 주소값, c
와 d
는 다른 주소값을 가지고 있다는 것을 알 수 있었습니다.
다시 처음으로 돌아와서, 우리는 주소값보다는 실제 데이터값을 비교하는 상황이 많습니다. 그런데, 왜 ==
연산자를 사용한 결과와 equals()
메서드를 사용한 결과가 다른 것인지 알아보기 위해 여기까지 왔습니다.
그 차이점은 바로 ==
연산자는 주소값을 비교하는 반면,
equals()
메서드는 실제 값을 비교하기 때문입니다.
이 연산자는 비교 대상이 동일한 객체를 참조하는지 여부를 판단하는 연산자입니다. 즉, 객체의 주소값을 비교합니다. 예로 들었던 코드를 ==
연산자를 통해 비교해보겠습니다.
String a = "Chill";
String c = new String("Chill");
if (a == c) {
System.out.println("같음");
}
else {
System.out.println("다름");
}
다름
a
는 Stirng Pool에 저장된 반면, c
는 Heap 영역에 저장되어 있기 때문에, 서로 다른 객체를 가리키고 있습니다.
따라서 실제 데이터 값은 같을 지 몰라도, 객체의 주소값을 비교하는 ==
연산자는 다르다고 판단하는 것입니다.
이 메서드는 비교하는 두 대상의 값 자체를 비교하는 메서드입니다. 마찬가지로 예를 들어보겠습니다.
String a = "Chill";
String c = new String("Chill");
if (a.equals(c)) {
System.out.println("같음");
}
else {
System.out.println("다름");
}
같음
a
와 c
는 서로 주소값이 다르지만, equals()
메서드는 데이터 값을 비교하기 때문에, 변수 생성 방법에 따라 영향을 받지 않는 모습을 볼 수 있습니다.
결론적으로, String 변수를 서로 비교할 때
실제 데이터 값을 비교해야 한다면, equals()
메서드를 사용해야 합니다.