equals()와 hashCode()

곽동현·2022년 11월 1일
post-thumbnail

1. Object class


public class Student {
	private final String name; // 필드
    
    public Student(String name) { // 생성자
    	this.name = name;
   }
	
   public String getName() { // Getter Method
   		return name;
   }

Student a = new Student("john");
Student b = new Student("john");

Set<Student> set = new HashSet<>(Arrays.asList(a, b));

System.out.println(a.equals(b)); // false 
System.out.println(set.size()); // size = 2

System.out.println(a.hashCode()); //111~
System.out.println(b.hashCode()); // 201~

Student 클래스에서 equals()를 재정의하지 않고 선언하면 최상위인 Object 클래스의 equals()를 사용하게 된다.
equals 함수의 구조를 자세히 들여다보면 객체의 주소값을 비교하는 것이다. new Student(String name)으로 생성된 객체들은 Heap memory 내에서 서로 다른 주소값을 갖는다. 서로 다른 객체 a,b는 같은 이름의 속성인 john을 가지고 있지만 서로 다른 주소값을 갖고 있으므로 equals는 false를 반환하는 것이다.

그렇다면 hashCode() 함수는 어떤 역할일까?
hashCode()는 생성된 객체의 hashcode를 반환한다. 즉, 객체의 주소값을 변환해서 int type으로 반환하는 것이다. 마찬가지로 a와 b는 Heap memory 내 서로 다른 주소값을 가지고 있으므로 서로 다른 해시값이 리턴되는 것이다.


2. String class

이번엔 String 클래스를 이용하여 객체를 생성해보고 무엇이 다른지 알아보자, 객체를 생성하는 방법은 new 메소드리터럴 방식이 있다.

String a = new String("john");
String b = new String("john");
String c = "john";
String d = "john";

System.out.println(a.equals(b)); // abcd 동일
...

System.out.println(a.hashCode()); //abcd 동일
...

System.out.println(System.identityHashCode(a)); // 10...
System.out.println(System.identityHashCode(b)); // 201...
System.out.println(System.identityHashCode(c));
System.out.println(System.identityHashCode(d));

Object 클래스의 hashCode()는 주소값을 반환하지만
String 클래스의 hashCode()는 주소값을 리턴하지 않는다.
실제 주소값은 identityHashCode()로 확인이 가능한데,
여기서 a,b는 Heap Memory 내에서 서로 다른 영역에 저장된 것을 한번 더 알 수 있다. 따라서 String 클래스의 equals()는 단순히 주소값을 비교하는 것이 아니라 실제 문자열을 비교해서 true, false를 판단하는 것이다.

즉, String 클래스는 Object 클래스의 equals 메서드를 그대로 사용하지 않고 String 클래스의 특성에 맞게 재정의해서 사용한다는 것을 알 수 있다.

반면에 리터럴로 선언한 c와 d는 같은 값이다. 왜 String 클래스에서 리터럴로 생성한 c,d는 실제 주소값이 같은 것일까?
이유는 리터럴 생성은 String Pool 이라는 곳에 저장되기 때문이다. 메모리 효율성을 고려하였을 때, new String() 객체로 생성하기 보다는 리터럴 방식으로 생성하는게 효과적일 수 있다.

profile
읽고 쓰며 생각합니다 💡

2개의 댓글

comment-user-thumbnail
2023년 4월 7일

Q1. "new Student(String name)으로 생성된 객체들은 Heap memory 내에서 서로 다른 주소값을 갖는다." 라고 하셨는데 왜 다른가요?
Q2. Object 클래스의 equals() 를 직접 보여주시면 더 좋을 것 같아요!
Q3. "String 클래스의 hashCode()는 주소값을 리턴하지 않는다." 그러면 무엇을 리턴하나요?
Q4. 그렇다면 Student 클래스에 equals만 재정의한 상태로, Set 컬렉션에 같은 Student 객체를 넣어도 중복이 제거 되나요?

1개의 답글