Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 자바의 정석 기초편 ch9
- 자바의 정석 기초편 ch6
- 타임리프 - 기본기능
- jpa 활용2 - api 개발 고급
- 자바의 정석 기초편 ch12
- 스프링 db2 - 데이터 접근 기술
- 자바의 정석 기초편 ch4
- 스프링 mvc2 - 타임리프
- 자바의 정석 기초편 ch5
- 자바의 정석 기초편 ch2
- 코드로 시작하는 자바 첫걸음
- 스프링 mvc1 - 스프링 mvc
- 자바의 정석 기초편 ch13
- 스프링 고급 - 스프링 aop
- 스프링 mvc2 - 로그인 처리
- 2024 정보처리기사 수제비 실기
- 자바의 정석 기초편 ch14
- 자바의 정석 기초편 ch7
- 자바의 정석 기초편 ch8
- 스프링 mvc2 - 검증
- 자바의 정석 기초편 ch11
- 스프링 db1 - 스프링과 문제 해결
- 스프링 입문(무료)
- @Aspect
- jpa - 객체지향 쿼리 언어
- 스프링 mvc1 - 서블릿
- 게시글 목록 api
- 자바의 정석 기초편 ch1
- 자바의 정석 기초편 ch3
- 2024 정보처리기사 시나공 필기
Archives
- Today
- Total
나구리의 개발공부기록
자바의 정석 기초편 ch9 - 1 ~ 6 [Object클래스, equals(), hashCode(), toString()] 본문
유튜브 공부/JAVA의 정석 기초편(유튜브)
자바의 정석 기초편 ch9 - 1 ~ 6 [Object클래스, equals(), hashCode(), toString()]
소소한나구리 2023. 12. 5. 15:021) Object 클래스
- 모든 클래스의 최고조상
- 오직 11개의 메서드만을 가지고 있음
- notify(), wait() 등은 쓰레드와 관련된 메서드 - 13장에서 배움
- protected라고 되어있는 메서드들은 오버라이딩하여 public으로 변경해야 다른곳에서 사용할 수 있음
Object클래스의 메서드 | 설명 |
protected Object clone() | 객체 자신의 복사본을 반환, 객체 복사에 사용 |
public boolean equals(Object obj) | 객체 자신과 객체 obj가 같은 객체인지 알려줌 (같으면 true), 객체 비교에 사용 |
protected void finalize() | 객체가 소멸 될 때 가비지 컬렉터에 의해 자동으로 호출 이 때 수행되어야 하는 코드가 있을 때 오버라이딩 거의 사용안함 - 마무리 작업에 사용하는 메서드인데 메모리가 부족한 상황에서 프로그램이 종료 되어야 하는데 finalize에 코드가 있으면 메모리정리에 시간이 많이 걸리게 되는 문제가 있음 |
public Class getClass() | 객체 자신의 클래스 정보를 담고 있는 Class인스턴스를 반환 class Class { } -> 클래스 정보를 담기위한 클래스 |
public int hashCode() | 객체 자신의 해시코드를 반환 |
public String toString() | 객체 자신의 정보를 문자열로 반환 |
public void notify() | 객체 자신을 사용하려고 기다리는 쓰레드를 하나만 깨움 |
public void notifyAll() | 객체 자신을 사용하려고 기다리는 모든 쓰레드를 깨움 |
public void wait() public void wait(long timeout) public void wait(long time out, int nanos) |
다른 쓰레드가 notify()나 notifyAll()을 호출할 때까지 현재 쓰레드를 무한히 또는 지정된 시간(timeout, nanos)동안 기다리게함 (timeout은 천분의 1초, nanos는 10의9제곱 분의 1초) |
2) equals (Object obj)
- 객체 자신(this)과 주어진 객체(obj)를 비교하여 같으면 true 다르면 false를 반환
- Object클래스의 equals()는 객체의 주소를 비교 즉, 참조값을 비교함
- iv값을 비교하기 위해 equals()를 이용할 경우 false가 나옴(모든 객체의 주소는 다름) -> 오버라이딩이 필요함
public boolean equals(Object obj) {
return (this==obj); // 파라미터로 입력받은 obj와 this(객체자신과)참조값을 비교
}
(1) 예제
- ValueOver 클래스에서 equals()를 오버라이딩하여 참조값이 아닌 값을 변경하도록 변경
- Value객체를 생성하여 참조값을 저장한 변수들을 비교하면 false가 나오고, ValueOver 객체를 생성하여 참조값을 저장한 변수들을 비교하면 실제 값을 비교하게 되므로 값이 같다면 true가 나옴
class Ex9_1 {
public static void main(String[] args) {
Value v1 = new Value(10); // Value 객체 생성
Value v2 = new Value(10);
if (v1.equals(v2)) // v1과 v2의 주소 비교
System.out.println("v1과 v2는 같습니다.");
else
System.out.println("v1과 v2는 다릅니다.");
ValueOver v3 = new ValueOver(10); // ValueOver 객체 생성
ValueOver v4 = new ValueOver(10);
if (v3.equals(v4)) // v3과 v4의 실제 값을 비교
System.out.println("v3과 v4는 같습니다.");
else
System.out.println("v3과 v4는 다릅니다.");
} // main
}
class Value {
int value;
Value(int value) {
this.value = value;
}
}
// 오버라이딩 하여 서로다른 객체라도 값이 같으면 true를 반환하도록 변경
class ValueOver {
int value;
ValueOver(int value) {
this.value = value;
}
// Object의 equals() 메서드를 주소가 아닌 실제 값을 비교하도록 오버라이딩
public boolean equals(Object obj) {
// 참조변수의 형변환 전에는 반드시 instanceof로 확인해야함.
if(!(obj instanceof ValueOver)) return false;
ValueOver v = (ValueOver)obj; // 조상타입의 obj를 ValueOver타입으로 형변환
return this.value==v.value; // 오버라이딩 하여 실제 값을 비교하도록 재정의
}
}
(2) 예제2
- 동일한 메커니즘의 예제
class Person {
long id; // this.id
// equals()메서드 오버라이딩
public boolean equals(Object obj) {
if(!(obj instanceof Person))
return false;
// Person p = (Person)obj;
// return this.id == p.id;
return id ==((Person)obj).id; // 위 2줄코드를 한줄로(this. 생략)
}
Person(long id) {
this.id = id;
}
}
class Ex9_2 {
public static void main(String[] args) {
Person p1 = new Person(8011081111222L);
Person p2 = new Person(8011081111222L);
if(p1.equals(p2))
System.out.println("p1과 p2는 같은 사람입니다.");
else
System.out.println("p1과 p2는 다른 사람입니다.");
}
}
3) hashCode()
- 객체의 해시코드를 정수타입으로 반환하는 메서드
- 동등한 객체들은 같은 해시코드를 반환해야 하며, 이는 객체를 식별하고 비교하는 데 사용되어 객체의 지문이라고도 불림
- 해시코드는 정수타입으로 표현되며 해싱알고리즘으로 생성됨(11장 컬렉션 프레임워크 추가로 배움)
- equals()를 오버라이딩 하면, hashCode()도 오버라이딩 해야 하는데 이유는 equals()의 결과가 true이면 두 객체가 같다는 뜻인데 hashCode()가 다르면 논리상 어긋나기 때문, 즉 equals()와 hashCode()는 서로 일관성을 유지해야 함
- 해시충돌로 인하여 서로 다른 객체라도 같은 해시코드를 가질 수 있는데 이를 위한 다양한 해결방법이 있음 -> 별도 검색 필요
public class Object {
...
// 네이티브메서드 : OS의 메서드(C언어),
public native int hashCode(); // 내용이 없음 - 이미 작성되어있는 OS의 메서드를 사용
// OS가 가지고있는(C언어로 작성되어있는)메서드들을 Java에서 사용할 수 있도록 함
// JNI라는 기술도 있음
(1) 예제1
- String클래스는 이미 equals()와 hashCode()가 오버라이딩 되어있어서 일관성있게 출력되므로 String클래스의 hashCode로 값을 출력해 보면됨
- 오버라이딩 전의 해시코드를 보고싶다면 identityHashCode()를 사용하면됨
class Ex9_3 {
public static void main(String[] args) {
// String클래스에는 equals와 hashCode가 이미 오버라이딩 되어있음
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1.equals(str2));
System.out.println(str1.hashCode()); // 오버라이딩 된 hashCode 출력
System.out.println(str2.hashCode());
// Object클래스의 hashCode 출력
System.out.println(System.identityHashCode(str1));
System.out.println(System.identityHashCode(str2));
}
}
** 참고
- 32bit JVM = 주소값 int 타입
- 64bit(8byte) JVM = 주소값 Long 타입
- 64bit의 JVM으로 해시코드를 만들면 8byte 에서 4byte로 바뀌어 정보의 손실이 있을 수 있음
4) toString()의 오버라이딩
- 객체를 문자열로 변환하기 위한 메서드
- Object의 toString()은 객체의 주소값을 반환(엄밀히 말하면 16진수로 표시된 해시코드값이 출력되는 것)
- 주소값이 아닌 iv값(실제 논리적인 값)을 출력 하고자 하면 오버라이딩 해야 함
public String toString() { // Object클래스의 toString
return getClass().getName()+"@"+Integer.toHexString(hashCode());
// 클래스객체 클래스이름 16진 해시코드 반환
}
(1) toString(), equals(), hashCode() 오버라이딩 예제
- equals()와 hashCode()를 오버라이딩하여 일관성을 유지
- toString()을 오버라이딩하여 출력 형식을 커스텀하여 toString()를 호출하면 형식에 맞춰서 출력됨
import java.util.Objects;
class Card {
String kind;
int number;
Card() {
this("SPADE", 1);
}
Card(String kind, int number) {
this.kind = kind;
this.number = number;
}
// equals()를 오버라이딩하면 hashCode()도 오버라이딩 해야함.
public int hashCode() {
return Objects.hash(kind, number);
}
// equals()오버라이딩
public boolean equals(Object obj) {
if(!(obj instanceof Card))
return false;
Card c = (Card)obj;
return this.kind.equals(c.kind) && this.number==c.number;
}
// Object클래스의 toString()을 오버라이딩
public String toString() {
return "kind:" + kind + ", number:" + number;
}
}
class Ex9_4 {
public static void main(String[] args) {
Card c1 = new Card();
Card c2 = new Card();
System.out.println("c1과 c2가 같나요? "+c1.equals(c2));
System.out.println("c1의 값은? "+c1.toString());
System.out.println("c2의 값은? "+c2.toString());
System.out.println("c1의 hashCode는? "+c1.hashCode());
System.out.println("c2의 hashCode는? "+c2.hashCode());
}
}
출력값
c1과 c2가 같나요? true
c1의 값은? kind:SPADE, number:1
c2의 값은? kind:SPADE, number:1
c1의 hashCode는? -1842861219
c2의 hashCode는? -1842861219
** 참고
- equals()와 hashCode()의 오버라이딩이 필요한 경우 IDE에서 해당 기능을 자동으로 완성시켜주는 기능이 존재함
- 이클립스는 오른쪽버튼 -> Source에, 인텔리제이는 컨트롤 + 엔터를 치면 equals() and hashCode()라는 메뉴가 있음
** 출처 : 남궁성의 정석코딩_자바의정석_기초편 유튜브 강의