JAVA

[JAVA] 자바의 Object 클래스와 메서드 정리

작소율 2025. 4. 18. 22:41

자바의 Object 클래스

Object 클래스는 자바의 모든 클래스가 기본적으로 상속 받는 최상위 클래스이다.

이 클래스는 equals, hashCode, toString과 같은 메서드를 제공한다.

 

equals 메서드

현재 객체와 매개 변수로 넘겨받은 객체가 같은지 확인하여, 같으면 true, 다르면 false를 반환한다.

기본 타입의 int형, char형등은 Call by Value 형태로 기본적으로 대상에 주소값을 가지지 않는 형태로 사용하기 때문에 equals 메서드 사용 시 값을 전제로 비교한다. 하지만 객체의 동등성 비교에서는 이 메서드를 재정의 해주지 않으면, 같은 값을 가진 두 객체를 비교할 때 equlas()는 객체타입의 주소 값을 비교하기 때문에 서로 다른 메모리에 할당된 두 객체는 다르다고 인식한다.

하지만, 데이터적인 입장에서는 두 객체는 같기 때문에 이를 equals 메서드를 통해 재정의 해주어야한다.

String 클래스의 equals 메서드가 Object 클래스의 equals 메서드를 재정의한 대표적인 예이다.

 

hashCode 메서드

int hashCode() 로 정의된 hashcode 메서드는 실행중에 유일한 integer 값을 반환한다.

이는 객체에 대한 해시 코드값을 리턴한다. 16진수로 제공되는 객체의 메모리 주소를 해싱(hashing)기법을 통해 해시코드를 만든 후 반환한다. 즉, 객체의 주소값으로 만든 고유한 숫자값이다.

자바에서는 포인터를 숨긴 구조라 객체의 직접적인 원본 주소를 얻을 수 없다. 그래서 자바에서는 참조 변수의 주소값을 표현하기 위해서 hashcode 를 이용한다.

 

 

equals 메서드'만' 재정의를 한다면?

equals 메서드를 재정의할 때는 hashcode 메서드도 함께 재정의 해줘야 한다. equals 메서드에 의해 동등하다고 판단된 객체들이 hashCode 메서드에 의해 같다고 판단되어야 하기 때문이다. 그렇지 않았을 때의 예시를 보면 아래와 같다.

 

class Person {

	public String name;
    
    public Person(String name) {
    	this.name = name;
    }
    
    @Override
    public boolean equals(Object o) {
    	if (this == 0) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person p = (Person) o;
        
        if(this.name.equals(p.name)) {
        	return ture; // 필드 값이 같으면, 같은 객체로 판단하도록 재정의
        }
        
        return false;
    }


}

public class PersonExample {

    public static void main(String[] args) {
    	
        Person person1 = new Person("홍길동");
        Person person2 = new Person("홍길동");
        
        // 두 객체의 할당된 메모리 주소가 다르기 때문에 해시코드 또한 다른 값으로 나옴.
        System.out.println(person1.hashCode());
        System.out.println(person2.hashCode());
        
        // 해시 코드가 달라도, equals 를 재정의 했기 때문에 true 가 나옴.
        System.out.println(person1.equals(person2)); // true
        
        
        // 중복이 허용되지 않는 HashSet에 이름이 같은 두 Person 객체를 넣었을 때
    	Set<Person> persons = new HashSet<>();
        persons.add(person1);
        persons.add(person2);
        
        System.out.println(persons.size()); 
        
    }
    

}

 

equals 메서드를 재정의 하여 필드 값이 같으면 논리적으로 같다고 정의하였지만, 해시코드가 다르기 때문에 hashSet의 사이즈는 예상했던 것과 달리 2가 나온다. 

 

위처럼 동작하는 이유는 hash 값을 사용하는 Collection (HashMap, HashSet, HashTable) 은 객체가 논리적으로 같은지 비교할 때 

그 데이터의 hashCode() 리턴 값이 컬렉션 리스트에서 가지고 있는지를 비교한다. 만약 해시코드가 같다면 그제서야 다음으로 equals() 메서드를 통해 리턴 값을 비교하여 true 이면 논리적으로 같다고 판단한다.

 

결국, hash 기반의 Collection 에 값을 넣을 때, 두 객체를 equals 로 비교하기도 전에 hashCode 메서드에 의해 다른 객체로 판단하게 되어 의도와 다르게 저장되는 것이다.

 

따라서 이와같이 의도한 바와 다른 오작동이 일어나지 않게 하려면 hashCode 메서드도 함께 재정의 해줘야한다. 

 

 

equals 메서드와 hashCode 메서드 재정의

 

class Person {

	public String name;
    
    public Person(String name) {
    	this.name = name;
    }
    
    @Override
    public boolean equals(Object o) {
    	if (this == 0) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person p = (Person) o;
        
        if(this.name.equals(p.name)) {
        	return ture; // 필드 값이 같으면, 같은 객체로 판단하도록 재정의
        }
        
        return false;
    }
    
    @Override
    public Integer hashCode() {
    	return Objects.hashCode(name); // name 필드의 해시값을 반환.
    }


}

public class PersonExample {

    public static void main(String[] args) {
    	
        Person person1 = new Person("홍길동");
        Person person2 = new Person("홍길동");
        
        // 두 객체의 할당된 메모리 주소는 다르지만 
        // 해시코드 메서드를 재정의 했기 때문에 해시코드가 같은 값으로 나옴.
        System.out.println(person1.hashCode());
        System.out.println(person2.hashCode());
        
        // 해시 코드가 달라도, equals 를 재정의 했기 때문에 true 가 나옴.
        System.out.println(person1.equals(person2)); // true
        
        
        // 중복이 허용되지 않는 HashSet에 이름이 같은 두 Person 객체를 넣었을 때
    	Set<Person> persons = new HashSet<>();
        persons.add(person1);
        persons.add(person2);
        
        System.out.println(persons.size()); // 1로 출력됨
        
    }
    

}

 

hashCode 메서드를 재정의함에 따라, 두 객체의 해시코드가 같은 값이 나오고 해시기반 Collection에 저장할 때 중복된 데이터로 판단되어 한개만 추가됨을 볼 수 있다.


Java 에서 hashCode 값은 고유한 값이 아닌 이슈도 있는데 해당 부분은 다음 포스팅으로 작성할 예정이다.

자바의 문법만 알았지 이런 근원적인 부분을 좀 더 세심히 공부하지 못한 점을 깊게 반성하며 포스팅을 작성했다.

차근차근 하면 된다 !! 돈깁업 저스트두잇 앤드 인조이 🚀