Object 클래스의 hashCode 메서드
Java에서 사용되는 해시 코드(Hashcode)는 객체를 식별하기 위한 ID입니다. Java의 모든 객체는 JVM에 의해 고유 번호가 생성되며, 이 고유 번호가 해시 코드입니다.
해시 코드는 32 비트 고유한 정수 값으로 객체와 다른 객체를 구별하기 위해 사용되며, 객체의 내부 주소를 정수로 변환된 값입니다.
해시 코드를 사용하는 이유
다른 프로그래밍에서는 해시 코드를 거의 사용하지 않지만, Java는 해시 코드를 자주 사용합니다. HashTable, HashSet, HashMap 같은 클래스의 이름만 봐도 해시 코드를 사용한다는 것을 짐작할 수 있죠.
Java에서 해시 코드를 기반으로 데이터를 관리하는 이유는 데이터 검색, 추가, 제거하는 작업이 쉬워지며, 시간 복잡도가 O(1)이므로 상당히 빠르게 동작하기 때문입니다.
hashCode 메서드 사용 방법
Object 클래스에 존재하는 hashCode() 메서드는 비정적(non-static) 메서드이므로 객체를 생성해야 호출할 수 있습니다.
public native int hashCode();
hashCode() 메서드의 반환 결과는 객체의 내부 주소를 정수로 변환하여 반환합니다.
Java의 모든 클래스는 최상위 클래스인 Object에서 파생됩니다. 따라서, 모든 클래스의 인스턴스는 hashCode() 메서드를 호출할 수 있습니다.
다음 예제는 Person 클래스의 객체를 2개 선언하고 hashCode() 메서드를 호출한 결과를 출력합니다.
[Person 클래스]
public class Person {
private String Name;
private Integer Age;
}
[Main문]
public static void main(String args[]) {
Person person1 = new Person();
Person person2 = new Person();
System.out.println(person1.hashCode());
System.out.println(person2.hashCode());
}
[실행 결과]
1118140819
1975012498
person1, person2 객체는 내부 주소가 다르므로 서로 다른 해시 코드를 가집니다. 그리고 해시 코드는 항상 동일하지 않습니다.
컴퓨터마다 메모리 구조와 사양이 다르므로 객체가 생성되는 위치가 다릅니다. 위 예제를 다른 컴퓨터에서 실행하면 다른 해시 코드가 반환됩니다.
hashCode 메서드 재정의
모든 클래스는 hashCode() 메서드를 재정의할 수 있습니다. 따라서, 개발자가 원하는 값을 반환하도록 수정할 수 있습니다.
다음 예제는 Person 클래스의 hashCode() 메서드가 Age 필드의 값을 반환하도록 재정의되었습니다.
[Person 클래스]
public class Person {
private String Name;
private Integer Age;
public Person(){};
public Person(String name, Integer age) {
Name = name;
Age = age;
}
@Override
public int hashCode() {
return Age;
}
}
[Main문]
public static void main(String args[]) {
Person person1 = new Person("둘리", 10);
Person person2 = new Person("또치", 20);
System.out.println(person1.hashCode());
System.out.println(person2.hashCode());
}
[실행 결과]
10
20
hashCode 메서드 이해하기
다음은 hashCode() 메서드를 사용하거나 재정의하기 전에 꼭 알아야 하는 내용입니다.
1. hashCode() 메서드는 항상 해시 코드를 반환하지 않는다.
위 예제처럼 hashCode() 메서드를 재정의하면, 사용자가 원하는 값을 반환하도록 수정할 수 있습니다. 하지만, hashCode() 메서드를 재정의했다고 객체의 내부 주소가 바뀌는 것은 아닙니다. 재정의되지 않은 hashCode() 메서드는 객체의 내부 주소를 해시 코드로 변환하는 기능만 수행합니다.
2. 객체의 내부 주소가 변경되면 해시 코드도 변경된다.
재정의되지 않은 hashCode() 메서드는 객체의 내부 주소를 해시 값으로 변환하여 반환합니다. 만약, 객체의 내부 주소가 변경되면 hashCode() 메서드의 반환 결과도 달라집니다.
다음 예제는 hashCode() 메서드가 재정의되지 않은 Person 클래스의 객체 두 개를 생성 후 hashCode() 메서드를 호출합니다. 그다음으로 person1에 person2를 할당 후 hashCode() 메서드를 호출하면, 반환 결과가 동일한 것을 볼 수 있습니다.
public static void main(String args[]) {
Person person1 = new Person();
Person person2 = new Person();
System.out.println("[변경 전]");
System.out.println(person1.hashCode());
System.out.println(person2.hashCode());
person1 = person2;
System.out.println("\n[변경 후]");
System.out.println(person1.hashCode());
System.out.println(person2.hashCode());
}
[실행 결과]
[변경 전]
1118140819
1975012498
[변경 후]
1975012498
1975012498
3. 동일한 해시 코드를 반환받을 수 있다.
두 개 이상의 객체가 hashCode() 메서드를 호출하여 동일한 해시 코드를 반환받을 수 있습니다. 첫 번째 방법으로 hashCode() 메서드를 재정의하여 동일한 값을 반환하도록 수정합니다. 두 번째 방법으로 = 연산자를 사용하여 객체를 다른 객체에 할당합니다.
해시 코드를 가져오는 또 다른 방법
Object 클래스의 hashCode() 메서드를 사용하지 않고 해시 코드를 가져올 수 있습니다.
첫 번째 방법으로 System 클래스의 identityHashCode() 메서드에 객체를 전달합니다.
public static void main(String args[]) {
Person person1 = new Person();
Person person2 = new Person();
System.out.println(System.identityHashCode(person1));
System.out.println(System.identityHashCode(person2));
}
[실행 결과]
1118140819
1975012498
System 클래스의 identityHashCode() 메서드는 재정의할 수 없으므로 객체의 내부 주소를 기반으로 해시 값을 반환합니다.
반면에 hashCode() 메서드는 재정의할 수 있으므로 객체의 내부 주소를 기반으로 해시 값을 반환하는지 소스 코드를 확인하지 않는 이상 알 수 없습니다.
'Java' 카테고리의 다른 글
[Java]hashCode와 equals 메서드 (0) | 2022.09.04 |
---|---|
[Java]Object 클래스의 equals 메서드 (0) | 2022.09.03 |
[Java]Object 클래스의 getClass 메서드 (0) | 2022.09.03 |
[Java]Object 클래스의 toString 메서드 (0) | 2022.09.02 |
[Java]난수 생성 방법 (0) | 2022.08.31 |
댓글