Java에서 equals()
와 ==
는 객체 혹은 내용을 비교할 때 사용하곤 한다.
이 둘은 어떤 차이점이 있을까?
== : 동일성 비교
- Primitive Type(int, float, double, long 등)일 경우에는 값이 같은 지 확인
- 그 외에 객체나 Reference Type일 경우에는 주소가 같은지 확인
1 | //리터럴 생성 |
String의 경우는 조금 특별한데, 리터럴 생성을 하면 String Constant Pool 이라는 영역에 할당되고, new 를 이용한 생성을 하면 Heap에 할당된다.
리터럴로 생성한 문자가 같을 경우 메모리 상에서 같은 주소를 바라보게 되고,
new로 생성할 경우 생성 할 때마다 새로운 인스턴스를 생성하여 각각 다른 주소 공간에 위치하게 된다.
그렇기 때문에
str1 == str2
: 리터럴로 생성되어 같은 주소를 바라보고 있기 때문에 truestr3 == str4
: new로 생성되어 각각 다른 주소에 생성되기 때문에 falsestr1 == str3
: 리터럴과 new로 생성되어 서로 다른 주소에 위치하기 때문에 false
결론적으로==
두 객체가 같은 주소를 가르킬 때 true를 반환한다.
equals() : 동등성 비교
- Primitive Type(int, float, double, long 등)일 경우에는 값이 같은 지 확인
- 그 외 객체나 Reference Type일 경우에는 주소가 같은지 확인
==
과 유사하지만 다른 점은 완전히 같은 객체(같은 주소)를 가리키지 않아도equals()
메서드 오버라이딩을 통해서 true로 만들 수 있다.
1 | String str1 = "hi"; |
String에는 이미 equals()
메소드가 오버라이딩 되어 있는 상태이기 때문에 주소값이 다르더라도 내용이 같다면 true를 반환하고 있다.
1 | Student s1 = new Student("1"); |
Student 객체를 만든 뒤 동일한 id 값을 부여한 후 비교하면 주소 값이 다르기 때문에 false를 반환한다. (hash 값도 다르다.) true로 만들기 위해서는 equals()
와 hashcode()
메소드를 오버라이딩 해준다. IDE에서 자동으로 생성해주나, 조건에 따라 수정하여 사용하도록 한다.
1 | public class Student { |
이후 코드를 재실행하면 결과 값은 true가 나오고 두 객체 모두 동일한 hash 값을 가지게 된다.
1 | Student s1 = new Student("1"); |
hashcode()
왜 오버라이딩하는지 궁금해 할 것이다. 우리도 모르는 사이에 hash값을 쓰는 곳이 많다. 예를 들면 hashSet
이나 hashmap
같은 컬렉션 들이다. equals()
만 오버라이딩하고 hashcode()
는 하지 않았을 경우엔 같은 객체라 할지라도 hashcode()
값이 다르게 나올 수 있는데, 이때는 다른 객체로 인식하기 때문이다.
1 | Set<Student> stu = new HashSet<>(); |
hashcode()
를 오버라이딩 한 경우 hashcode 값이 같으므로 같은 객체로 인식하여 1이 나온다. (Set은 중복 허용 X) 반면 오버라이딩을 하지 않았을 경우 hashcode 값이 다르므로 다른 객체로 인식하기 때문에 size 값은 2가 된다.
그러므로 equals()
를 오버라이딩 할 경우 반드시 hashcode()
도 오버라이딩 하여 혹시나 모를 불상사를 예방하는 것이 좋다.
정리
==
는 객체 간의 동일성을 판단하기 위해 사용한다. 동일성은 두 개의 객체가 완전히 같을 경우를 의미 한다.equals()
는 객체 간의 동등성을 판단하기 위해 사용한다. 동등성은 두 개의 객체가 같은 내용을 가질 경우를 의미 한다.==
연산자는 주소 값의 비교,equals()
는 내용을 비교 한다.equals()
를 오버라이딩 할 경우 반드시hashcode()
도 오버라이딩 하여야 한다.equals()
로 true가 나온 경우hashcode()
의 값이 동일 해야 한다. 그러나hashcode()
가 동일하다고 해서 반드시 같은 객체는 아니다.
참고 사이트
https://jeong-pro.tistory.com/172
https://joont.tistory.com/143
https://madplay.github.io/post/java-string-literal-vs-string-object