개요
자바에서 `==`(등가비교 연산자)와 `equals()`는 두 객체의 값이 같은지 비교할 때 사용하며 비교 결과를 boolean 타입으로 반환한다. 둘은 비슷해 보이지만 반대의 결과가 나오기도 하기 때문에 어떤 차이가 있는지 알아보고자 한다.
등가비교 연산자 `==`
두 피연산자의 값이 같은지를 비교하는 연산자로, 모든 자료형(기본형과 참조형)에 사용 가능하다.
기본형의 경우 변수에 저장되어 있는 값이 같은지 알 수 있고, 참조형의 경우 객체의 주소값이 같은지를 알 수 있다.
다시 말해 `==` 연산자는 비교 대상의 주소값을 비교한다.
int val1 = 3;
int val2 = 3;
int val3 = 5;
String str1 = "hello";
String str2 = new String("hello");
System.out.println(val1 == val2); // true
System.out.println(val1 == val3); // false
System.out.println(str1 == str2); // false
System.out.println(str1 == "hello"); // true
System.out.println(str2 == "hello"); // false
위 코드에서 str1과 str2는 모두 "hello"라는 값을 가지고 있지만, 주소값이 다른 객체이기 때문에 두 값을 비교하면 false의 결과를 얻는다.
따라서 문자열의 비교를 포함한 객체의 값을 비교할 때는 원하지 않은 결과를 얻을 수 있다.
`.equals()`
`equals()`는 String 클래스에 정의된 메서드로, 객체가 달라도 내용이 같으면 true를 반환한다.
위에서 보았듯 문자열을 비교한다면 `equals()`를 사용해야 한다.
String str1 = "hello";
String str2 = new String("hello");
System.out.println(str1.equals(str2)); // true
System.out.println(str1.equals("hello")); // true
System.out.println(str2.equals("hello")); // true
`str1 == str2`와 달리 `str1.equals(str2)`는 결과로 true를 얻는다.
만약 문자열이 아닌 객체를 비교할 때는 한 가지 고려해야 하는 부분이 있다.
테스트를 위해 TestData 객체를 생성하여 객체의 값을 비교하는 코드를 아래와 같이 작성하였다.
public class TestMain {
public static void main(String[] args) {
TestData data1 = new TestData(1, "hello");
TestData data2 = new TestData(1, "hello");
System.out.println(data1 == data2); // false
System.out.println(data1.equals(data2)); // false
}
static class TestData {
int id;
String name;
public TestData(int id, String name) {
this.id = id;
this.name = name;
}
}
}
TestData의 값을 동일하게 입력한 data1과 data2는 `==` 연산자와 `equals()` 결과 모두 false가 나온다.
객체의 필드값이 모두 동일한 경우 비교 결과가 true가 나오도록 하려면 `equals()`를 오버라이드해주도록 한다.
public class TestMain {
public static void main(String[] args) {
TestData data1 = new TestData(1, "hello");
TestData data2 = new TestData(1, "hello");
System.out.println(data1 == data2); // false
System.out.println(data1.equals(data2)); // true
}
static class TestData {
int id;
String name;
public TestData(int id, String name) {
this.id = id;
this.name = name;
}
// equals() 오버라이드 추가
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TestData testData = (TestData) o;
return id == testData.id && Objects.equals(name, testData.name);
}
}
}
이렇게 하면 객체의 모든 필드값을 비교한 결과를 얻을 수 있다.
참고로 이는 객체의 필드 개수와 상관이 없다.(필드가 1개뿐인 객체도 동일한 결과를 얻기 위해서 `equals()` 오버라이딩 필요)