반응형

hashCode()

  • 객체의 해시코드(hash Code)를 반환하는 메서드
  • Object클래스의 hashCode()는 객체의 주소를 int로 변환해서 반환

 

hashCode() 메서드는 객체의 해시코드를 반환하는 메서드다.
해시코드의 값은 정수값이다. 해싱이라는 알고리즘을 사용할때도 사용한다. 11장 컬렉션 프레임웍에서 자세히 바울 것이다.

그리고 Object클래스의 hashCode()메서드는, 객체의 주소를 int로 변환해서 반환한다.

 

실제 코드를 보면,
native라는 것이 붙어있는데, 이것은 네이티브 메서드라는 뜻이다.
네이티브 메서드란, OS란 가지고 있는 메서드라고 생각하면 된다.(C언어로 작성된 경우가 많음)
그리고, 구현부를 보면 없다. 즉 내용이 없다. 왜 내용이 없을까?
이미 작성되어 있는 메서드를 호출하는 것이기 때문이다.
이런식으로 메서드를 선언해 놓으면, OS가 가지고 있는 C언어로 작성된 메서드가 마치 Java로 작성된 메서드인 것 처럼 사용할 수 있다.
이것 말고도 자바와 자바가 아닌 언어가 서로 호출할 수 있도록 하는 JNI라는 기술도 있는데, 이런것이 있다는 정도만 참고로 알아두자.

이 OS에 작성되있는 메서드가 객체의 주소를 int로 변환해서  반환해주는 것이다. 
그 메서드의 내용을 볼 수는 없다. 단, 해당 메서드가 객체 주소를 반환해 준다는 점만 알고있으면 된다. 

그래서 객체의 주소를 int로 변환해서 반환하기 때문에, 객체마다 다른 값을 가진다. 
그래서 해시코드를 객체의 지문이라고도 한다. (객체마다 다른값이므로)

 

 

  • equals()를 오버라이딩하면, hashCode()도 오버라이딩해야 한다.
  • equals()의 결과가 ture면, 두 객체의 해시코드는 같아야 한다.

equals()와 hashCode()의 공통점이 둘다 객체주소를 가지고 작업을 한다는 것이다.

그런데 equals()를 보통 iv를 가지고 작업하도록 오버라이딩 한다.
그러면, hashCode()도 같이 iv를 이용해서 작업하도록 오버라이딩 해야한다.

왜냐하면 equals() 결과가 true면 두 객체의 해시코드는 같아야 하기 때문이다.

코드의 String클래스를 예로 들어보면, 

str1과 str2의 내용이 abc로 같은데, 
그러면 equals를 호출했을 때 true가 나오면, hashCode()값도 같아야 한다.
위 예제는 둘다 오버라이딩이 잘 되어있는 것이다.

 

  • System.identityHashCode(Object obj)는 Object클래스의 hashCode()와 동일

참고로, 아이덴티티 해쉬 코드라는 것이 있는데,
이것은, Object클래스의 hashCode()와 동일한 것이다. 
우리가 대부분 hashCode()를 오버라이딩 하는데,
오버라이딩 하기 이전의 기능이 필요할 때 이것을 사용한다.

이름에서 알 수 있듯, 객체마다 다른 해시코드를 반환한다. 

그래서 코드에서 처럼, str1, str2에 각각 identityHashCode()를 호출하면, 각각 다른 해시값이 나온다.

 

그리고, 32bit JVM에서는 주소값이 4byte인 Integer타입 값인데, 그래서 hashCode가 Int값인 것인데,
64bit JVM에서는 주소값이 8byte라서 long타입 값이다.

그래서  8byte 주소값을 4byte 주소값으로 만들면 겹치는 값이 나올 수 있다.

 


 

toString(), toString()의 오버라이딩

  • toString() : 객체를 문자열(String)으로 변환하기 위한 메서드

 

toString()은 객체를 문자열로 변환하기 위한 메서드다.

 

 

이 Object클래에 있는 toString은 이런 코드로 되어있다.

getClass()는 설계도 객체를 반환하는 메서드이고, getName()은 클래스 이름, @는 at의 의미이며 위치를 의미한다. 그리고 integer.toHexString은 16진수의 문자열로 바꿔서 출력하는 것이다. 객체주소값 hashcCode()를 말이다. 

그런데, hashCode()가 오버라이딩 되있는 경우에는, 다른 값이 나올 수 있다.

 

Card라는 클래스가 있을 때,
이 Card에 대해서 toString()을 호출하면, 결과값이 예제의 결과값처럼 나온다.

클래스이름@주소값 이 나온다. (엄밀히 이야기하면 주소값은 아니고, 주소값가지고 만든 값)

그러다보니, 객체마다 기본적으로 다른 값을 갖는데,
오버라이딩하면 값이 같을 수 있다. 

그런데, 기본적인 Object클래스에 있는 toString은 별로 유용하지가 못하다.
그래서 오버라이딩을 한다.

 

이런식으로 오버라이딩하는데, 
iv값을 이용해서 kind와 number값을 출력하도록 오버라이딩 하는 것이다. 

 

그러면, 결과가 바뀐다. 
원래는 클래스이름@주소 이런식으로 나왔는데, 오버라이딩 하고나니까 
kind : SPADE, number : 1이런식으로 결과가 바뀐다. 

왜 iv값을 출력하냐면,
객체 == iv집합 이므로
객체를 문자열로 변환한다는 것은 iv의 값을 문자열로 변환한다는 것과 같다.

위예제에서는 iv가 kind, number이다. 따라서 iv값들을 문자열로 바꾼다.
즉, 객체를 문자열로 변환한다는 것은 ,
iv값들을 문자열로 바꾸는 것과 같다.

그래서 이런식으로 오버라이딩하는 것이 일반적이다.

 

반응형

'JAVA' 카테고리의 다른 글

String 생성자  (0) 2022.04.15
String클래스, 문자열 비교, 빈 문자열  (0) 2022.04.14
Object클래스와 equals()  (0) 2022.04.13
연결된 예외  (0) 2022.04.12
사용자 정의 예외 만들기, 예외 던지기  (0) 2022.04.12