본문 바로가기
public void static main()/Book

[Effective Java] 아이템 10 ~ 아이템 11

by 햄리뮤 2023. 1. 10.
반응형

으어어ㅓㅓ어 맨날 스터디 전날에 공부해....

[책 규칙]

노란색 - 자세히 알아보고싶은 부분

초록색 - 핵심 개념 (블로그 정리시는 검은색으로!)

빨간색 - 무슨말인지 모르겠는 부분

넘나 어려운책...

 

[아이템 10] equals는 일반 규약을 지켜 재정의하라!

[아이템 11] equals를 재정의하려거든 hashCode도 재정의하라!!!!!

equals는 아예 재정의 하지 않는것이 아주 좋다고한다! 

그냥 둔다면 그 클래스의 인스턴스는 오직 자기 자신과만 같게 된다.

그러니 다음에서 열거한 상황 중 하나에 해당한다면 재정의 하지 않는 것이 최선이다.

  • 각 인스턴스가 본질적으로 고유하다.
    • 값을 표현하는 게 아니라 동작하는 개체를 표현하는 클래스가 여기 해당한다. Thread가 좋은 예로, Object의 equals 메서드는 이러한 클래스에 딱 맞게 구현되었다.
  • 인스턴스의 "논리적 동치성(logical equality)"을 검사할 일이 없다.
  • 상위 클래스에서 재정의한 euqals가 하위 클래스에도 딱 들어맞는다.
    • 대부분의 Set 구현체는 AbstractSet이 구현한 equals를 상속받아 쓰고, List 구현체들은 AbstractList로 부터, Map 구현체들은 AbstractMap으로부터 상속받아 그대로 쓴다.
  • 클래스가 private이거나 package-private이고 equals 메서드를 호출할 일이 없다.
    • euqlas가 실수라도 호출되는 걸 막고싶다면 아래 코드처럼 구현해두자
@Override
public boolean equals (Object o) {
	throw new AssertionError(); // 호출 금지!!
}

equals를 재정의해야할 때는 언제일까?

  • 객체 식별성(Object identity; 두 객체가 물리적으로 같은가)이 아니라 논리적 동치성을 확인해야 하는데, 상위클래스의 equals가 논리적 동치성을 비교하도록 재정의되지 않았을 때다. Integer와 String처럼 값을 표현하는 값 클래스들이 해당된다.

equals 메서드를 재정의할 때는 반드시 일반 규약을 따라야 한다. quals 메서드는 동치관계(equivalence relation)를 구현하며, 아래를 만족한다.)

  • 반사성(reflexivity) : 객체는 자기 자신과 같아야 한다.
  • 대칭성(symmetry) : 두 객체는 서로에 대한 동치 여부에 똑같이 답해야 한다.
  • 추이성(transitivity) : 첫 번째와 두 번째 객체가 같고, 두 번째 객체와 세 번째 객체가 같다면, 첫 번째 객체와 세 번째 객체도 같아야 한다.
  • 일관성(consistency) : 두 객체가 같다면(어느 하나 혹은 두 객체 모두가 수정되지 않는 한) 앞으로도 영원히 같아야 한다.
    • 클래스가 불변이든 가변이든 equals의 판단에 신뢰할 수 없는 자원이 끼어들게 해서는 안 된다.
  • null-아님: 모든 객체가 null과 같지 않아야 한다.  
주의사항
## equals를 재정의할 땐 hashCode도 반드시 재정의하자.
- equals 비교에 사용되는 정보가 변경되지 않았다면, 애플리케이션이 실행되는 동안 그 객체의 hashCode 메서드는 몇 번을 호출해도 일관되게 항상 같은 값을 반환해야 한다. 단, 애플리케이션을 다시 실행한다면 이 값이 달라져도 상관 없다.
-  equals(Object)가 두 객체를 같다고 판단했다면, 두 객체의 hashCode는 똑같은 값을 반환해야 한다.
- equals(Object)가 두객체를 다르다고 판단했더라도, 두 객체의 hashCode가 서로 다른 값을 반환할 필요는 없다. 단, 다른 객체에 대해서는 다른 값을 반환해야 해시 테이블의 성능이 좋아진다.
## 너무 복잡하게 해결하려 들지 말자.
- 필드들의 동치성만 검사해도 equals 규약을 지킬 수 있다.
해시 테이블?
Hash table(hash map) 이란 해시 함수를 사용해서 변환한 값을 index로 삼아 key와 value를 저장하는 자료구조를 말한다. 다시 말해 해시 테이블은 어떤 특정 값을 받아서 해시 함수에 입력하고, 함수의 출력 값을 인덱스로 삼아 데이터를 저장한다.

equals()와 hashCode()를 같이 재정의해야 하는 이유는?

hashCode()를 재정의 하지 않으면 같은 값 객체라도 해시값이 다를 수 있다. 따라서 HashTable에서 해당 객체가 저장된 버킷을 찾을 수 없다.

반대로 equals()를 재정의 하지 않으면 hashCode()가 만든 해시 값을 이용해 객체가 저장된 버킷을 찾을 수는 있지만 해당 객체가 자신과 같은 객체인지 값을 비교할 수 없기 때문에 null을 리턴하게 된다. 따라서 원하는 객체를 찾을 수 없다.

이러한 이유로 객체의 정확한 동등 비교를 위해서는 Object의 equals() 메소드만 재정의하지 말고 hashCode() 메소드도 재정의해서 논리적 동등 객체일경우 동일한 해시코드가 리턴되도록 해야한다.

equals 핵심 정리
꼭 필요한 경우가 아니면 equals를 재정의하지 말자, 많은 경우에 Object의 equals가 사용자가 원하는 비교를 정확히 수행해준다. 재정의해야 할 때는 그 클래스의 핵심 필드 모두를 빠짐없이, 다섯 가지 규약을 확실히 지켜가며 비교해야 한다.
hashCode 핵심 정리
equals를 재정의할 때는 hashcode도 반드시 재정의해야 한다. 그렇지 않으면 프로그램이 제대로 동작하지 않을 것이다. 재정의한 hashCode는 Object의 API 문서에 기술된 일반 규약을 따라야 하며, 서로 다른 인스턴스라면 되도록 해시코드도 서로 다르게 구현해야 한다. 

  • 아이템 개념
    • equals 메소드는 기본적으로 2개의 객체가 동일한지 검사하기 위해 사용된다. equals가 구현된 방법은 2개의 객체가 참조하는 것이 동일한지를 확인하는 것이며 이는 동일성(identity)을 비교하는 것이다.
    • hash code란 객체를 식별하는 하나의 정수값을 말한다. Object의 hashCode() 메소드는 객체의 메모리 번지를 이용해서 해시 코드를 만들어 리턴하기 때문에 객체 마다 다른 값을 가지고 있다.
  • 필요한 이유
    • equals()는 프로그래밍을 하다보면 동일한 객체가 메모리 상에 여러 개 띄워져있는 경우가 있다. 해당 객체는 서로 다른 메모리에 띄워져있으므로 동일한 객체가 아니다. 하지만 프로그래밍 상으로는 같은 값을 지니므로 같은 객체로 인식되어야 하는데, 이러한 동등성을 위해 값으로 객체를 비료하도록 equals 메소드를 오버라이딩 해줘서 사용한다.
    • hashCode는 hashTable과 같은 자료구조를 사용할 때 데이터가 저장되는 위치를 결정하기 위해 사용된다.
  • 아이템 개념의 반대 개념이나 관련 개념
    • 물리적 동치성 "==" 과 논리적 동치성 "equals"
    • 물리적 동치성 "=="
      • 메모리에 저장된 변수가 가지는 값이 서로 같은지 비교하는 것이다.
      • 단순하게 말하면 int, boolean과 같은 primitive type에 대해서는 값을 비교, reference typoe에 대해서는 주소값을 비교한다. 사실 primitive type도 Constant Pool에 있는 특정 상수를 참조하는 것이기 때문에 결국 주소값을 비교하는 것으로 볼수 있다.

너무 친절하게 설명해주신 블로거님글을 발견해서 가져와봤따 출처는 이미지 하단에! 더 자세한 내용이 있으니 블로그에 들어가서 읽어보면 좋을것이다!

[출처] https://javanitto.tistory.com/9

  • 실무에서는 어떤식으로 사용되는가 (실제 코드 사용예시)
  // equals()
  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Member member = (Member) o;
    return Objects.equals(userNo, member.userNo) 
    && Objects.equals(email, member.email) 
    && Objects.equals(name, member.name) && Objects.equals(password, member.password);
  }
// hashCode()
  @Override
  public int hashCode() {
    return Objects.hash(userNo, email, name, password);
  }
  • 장점
  • 단점

 

 

 

 

 

 

 

https://go-coding.tistory.com/35

 

[JAVA] String에서의 ==와 equals() 차이점

자바의 최상위 클래스는 Object클래스이다. Object클래스에는 기본적으로 equals(), hashCode(), toString(), clone(), notify()등 여러 메소드가 존재한다. 그 중에서도 우리가 가장 많이 사용하는 equals()에 대해

go-coding.tistory.com

https://javanitto.tistory.com/9

 

[ JAVA ] '=='와 'Equals' 비교 분석

개요 public class Main{ public static final void main(String[] args){ StringBuilder sb1 = new StringBuilder("apple"); StringBuilder sb2 = new StringBuilder("apple"); if(sb1.equals(sb2)){ System.out.println("같다"); } System.out.println("다르다"); }

javanitto.tistory.com

https://jisooo.tistory.com/entry/java-hashcode%EC%99%80-equals-%EB%A9%94%EC%84%9C%EB%93%9C%EB%8A%94-%EC%96%B8%EC%A0%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B3%A0-%EC%99%9C-%EC%82%AC%EC%9A%A9%ED%95%A0%EA%B9%8C

 

[java] hashcode()와 equals() 메서드는 언제 사용하고 왜 사용할까?

객체 비교(equals()와 ==) // Object의 기본 equals 메서드 public boolean equals(Object obj) { return (this == obj); } Object 클래스의 equals()는 위와 같은 기능으로써 이 메소드는 비교 연사자인 == 과 동일한 결과를 리

jisooo.tistory.com

https://mangkyu.tistory.com/101

 

[Java] equals와 hashCode 함수

1. equals와 hashCode란? equals와 hashCode는 모든 Java 객체의 부모 객체인 Object 클래스에 정의되어 있다. 그렇기 때문에 Java의 모든 객체는 Object 클래스에 정의된 equals와 hashCode 함수를 상속받고 있다. [ e

mangkyu.tistory.com

https://velog.io/@edie_ko/hashtable-with-js#:~:text=Hash%20table(hash%20map)%EC%9D%B4%EB%9E%80,%EC%82%BC%EC%95%84%20%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC%20%EC%A0%80%EC%9E%A5%ED%95%9C%EB%8B%A4. 

 

자료구조 | 해시 테이블 hash table

오늘은 해시 테이블의 기본 개념을 정리하고, 자바스크립트의 Object와 Map이 과연 정말로 해시 테이블인지 생각해본다.

velog.io

 

아~~ 힘두렁~~

 

 

** 그냥 하루하루 개인 공부한 것을 끄적 거리는 공간입니다.

이곳 저곳에서 구글링한 것과 강의 들은내용이 정리가 되었습니다.

그림들은 그림밑에 출처표시를 해놓았습니다.

문제가 될시 말씀해주시면 해당 부분은 삭제 하도록하겠습니다. **

반응형

'public void static main() > Book' 카테고리의 다른 글

[Effective Java] 아이템 15  (0) 2023.01.18
[Effective Java] 아이템 13  (0) 2023.01.10
[Effective Java] 아이템 3  (0) 2023.01.03
[Effective Java] 아이템 2  (0) 2023.01.03
[Effective Java] 아이템 1  (0) 2023.01.03

댓글