forDevLife
[java] hashCode(), toString(), equals() 본문
1. hashCode()
- 객체의 해시 코드를 반환하는 메서드
- Object 클래스의 hashCode()는 객체의 주소를 int로 변환해서(만들어서) 반환
public class Object {
...
public native int hashCode();
-> native 메서드(OS가 가지고 있는 메서드 - 주로 c로 작성)
-> 내용이 없음. 이미 작성되어있는 메서드를 사용함. 내용을 볼 수가 없다.
-> 객체마다 항상 다른 값이 나온다 = 객체의 지문
- equals() (-> iv)로 작업를 오버라이딩 하면, hashCode()도 오버라이딩해야 함. -> 둘 다 객체 주소로 작업
- equals의 결과가 true인 두 객체의 해시코드는 같아야 하기 때문!
+ 참고 : System.identity.HashCode(Object obj)는 Object 클래스의 hashCode()와 동일하게 객체의 주소값으로 해시코드 생성
-> String 클래스는 문자열 내용 같으면 동일한 해시코드 반환. 하지만 System~ 이거 이용하면 항상 다른 해시코드값 반환을 보장함
+ 32bit JVM : native int
64bit JVM : 8byte -> int 이므로, 주소값이 겹쳐 hashCode가 겹칠 수 있다.
+ 해싱 기법 사용하는 HashMap, HashSet 같은 클래스에 저장할 객체는 반드시 HashCode 메서드 오버라이딩 해야한다.
2. toString()
- 객체를 문자열(String)으로 변환하기 위한 메서드, 더 쓸모있는 정보를 제공할 수 있다.
public String toString() { // Object class의 toString()
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
- getClass() : 설계도 객체 // 클래스 생성되면 Class 클래스도 함께 생성된다. getClass()는 이 Class를 get 하는 메서드이다.
- getName() : 클래스 이름
- @ : 위치(at)
- Integer.toHexString : 16진 문자열로 바꿔서 출력
- hashCode() : 객체 주소를 int로 바꿈
package com;
class Card{
String kind;
int number;
Card() {
this("SPADE", 1);
}
public Card(String kind, int number) {
this.kind = kind;
this.number = number;
}
}
public class Ex14_0 {
public static void main(String[] args) {
System.out.println(new Card().toString());
System.out.println(new Card().toString());
Card card = new Card("king", 2);
System.out.println(card.toString());
}
}
- 클래스이름@객체 hashCode 순서로 출력이 된다.
- 객체는 iv(instance 변수) 집합 -> iv 값들을 문자열 결합으로 변경할 수 있다.
3. equals()
- String class 등은 Object 클래스의 equals 메서드를 그대로 사용하는게 아니라, 문자열 값을 비교하도록 오버라이딩 되어있다.
- 따라서 문자열.equals()로 비교가 가능한 것이다.
- StringBuffer클래스는 오버라이딩 되어있지 않다.
- 앞서 살펴본 것처럼, 클래스의 iv로 객체의 같고 다름을 판단할 경우, equals 및 hashCode를 둘 다 오버라이딩 해야한다고 했다.
- 같은 객체라면, hashCode 메서드를 호출했을 때의 결과값인 해시코드도 같아야하기 때문이다.
- hashCode 오버라이딩 하지 않는다면, Object 클래스에 정의된 대로 모든 객체가 서로 다른 해시코드 값을 가질 것이다.
4. getClass()
- 이 메서드는 자신이 속한 클래스의 Class 객체를 반환하는 메서드이다.
- 'Class' 객체는 이름이 'Class'인 객체이다. 아래와 같이 정의되어 있다.
public final class Class implements... { //Class 클래스
- Class 객체는 클래스의 모든 정보를 담고 있으며, 클래스 당 1개만 존재한다. 설계도 객체라고 한다.
- 이를 통해, 객체 생성, 정보 습득 가능하다.
- 동적으로 객체 생성 & 메서드 호출 하는 방법을 'ReflectionAPI' 라고 한다.
- 클래스 파일이 '클래스 로더'에 의해서 메모리에 올라갈 때 자동으로 생성된다.
* 클래스 로더 : 실행시에 필요한 클래스를 동적으로 메모리에 로드하는 역할
-> 기존에 생성된 클래스 객체가 메모리에 존재하는지 확인
-> 있으면 객체의 참조를 반환 / 없으면 클래스 패스에 지정된 경로를 따라서 클래스 파일을 찾는다.
-> 못 찾으면 ClassNotFoundException 발생, 찾으면 해당 클래스 파일 읽어서 Class 객체로 변환한다.
- 정리하자면, 파일 형태로 저장되어 있는 클래스를 읽어서 Class 클래스에 정의된 형식으로 변환하는 것이다.
- Class 객체를 얻는 방법
Class cObj = new Card().getClass(); // 생성된 객체로부터 얻기
Class cObj = Card.class(); // 클래스 리터럴(*.class)로 부터 얻는 방법
Class cObj = Class.forName("Card"); // 클래스 이름으로 부터 얻는 방법
Card c = new Card(); // new 연산자로 객체 생성
Card c = Card.class.newInstance(); // Class 객체를 이용해서 객체 생성
- c1, c2를 출력하면 오버라이딩 된 toString이 출력된다.
- cObj에 getClass를 통해 'Class' 클래스의 객체를 전달한다.
- getName() : 클래스 이름만 출력(class com.Card에서 com.Card만 출력)
- getClass() : 어쨌든 'Class' 클래스도 클래스이니, 얘의 정보를 출력한다. (class java.lang.Class)
- toGenericString() : Card 클래스의 추가 정보를 알려주는 듯?(final도 출력해줌)
- toString() : cObj만 출력하는 것과 동일하다.(당연)
'Java' 카테고리의 다른 글
[정규식] 문자열 계산기 (0) | 2021.09.30 |
---|---|
[java] import, static import 문 (0) | 2021.06.09 |
[java] 익명 클래스(anonymous class) (0) | 2021.05.28 |
[java] 디폴트 메서드, static 메서드 (0) | 2021.05.28 |
[자바의정석]Chapter 16. 네트워킹 (0) | 2021.04.19 |