습관적으로 사용할 수 있는 Object의 공통 메서드

박근수·2024년 11월 26일
0

01. equals의 일반 규약을 지켜 재정의하라

Equals가 만족해야하는 것

1. [reflexivity] e.quals(x) => true
2. [symmetry] x.equals(y) => true then y.equals(x) => true
3. [transitivity] x.equals(y) => true, y.equals(z) => true then x.equals(z) => true
4. [consistency] x.equals(y) 를 여러번 호출해도 항상 결과는 같게
5. [not null] if x is not null, then x.equals(null) = false

Equals의 전형적인 검사 패턴

  1. == 를 통해 input이 자기 자신의 참조인지
  2. instanceof를 통해 input의 타입이 명확한지
  3. 2를 통해 검사한 객체를 올바른 타입으로 형변환
  4. 핵심 필드등ㄹ이 모두 일치하는 지
  5. [not null] if x is not null, then x.equals(null) = false
@Override
public boolean equals(Object o){
	if(this == o) return true;
    if(o == null || getClass() != o.getClass()) return false;
    LaptopDto laptopDto = (LaptopDto) o;
    
    return Objects.equals(modelName, laptopDto.modelName) && Obejcts.equals(company, laptopDto.company);
}

주의사항

1. 만족해야 하는 조건을 만족시켰는가
2. Equals를 재정희 할 때 hashcode도 재정의 하였는가
3. Equals의 input이 Object인가 (Overriding 하였는가)
4. 핵심 필드들이 모두 일치하는 지
5. [not null] if x is not null, then x.equals(null) = false
    

02.equals를 재정의 하려거든 hashcode도 함께 재정의하라

비교 방복의 차이

==

value compare
즉 primitive type일 때는 value compar 
Reference type 일 때는 주소가 같은지 비교

equals()

메서드의 의도 : 같은 객체인지
Default : == 와 동일
Override하여 사용

hashcode()

논리적으로 같은 객체라면 같은 hashcode를 반환해야 함

간단한 방식의 hash

//가장 간단한 방식
@Override
public int hashCode(){
	int result = message.hashCode();
    return result;
}

//속도를 고려해야 한다면
@Override
public int hashCode(){
	return Objects.hash(modelName, company);
}

//속도가 많이 느려지만 lazy init, or caching을 고려하자

Object.hash() (내부에서 Array.hash 출력)

public static int hashCode(Object a[]){
	if (a == null) return 0;
    
    int result = 1;
    
    for (Object element : a){
    	result = 31 * result + (element == null ? 0 : element.hashCode());
    }
    return result;
}

Lombok을 사용하는 방법

@EqualsAndHashCode
public class EqualsAndHashCodeExample{
	private transient int transientVer = 10;
    private String name;
    private double score;
    private String[] tags;
    
    @EqualsAndHashCode.Exclude
    private int id;
}

03. toString을 항상 override 하라

toString의 일반 규약

간결하고 사람이 읽기 쉬운 형태의 유익한 정보

Lombok의 @ToString

@AllArgsConstructor
@ToString
public class Laptop{
	private String name;
    private String company;
}

System.out.println(new Laptop("그램 16인치", "LG"));
//실행 결과 : Laptop(name = 그램 16인치, company = LG)

불필요한 변수가 있을 경우

@ToString
public class Laptop{
	@ToString.Exclude
    private String modelName;
    private String company;
}

요약

1. 로그를 찍을 일이 있을 거 같으면 귀찮아하지 말고 toString을 overriding 하자.
2. 전부 다 toString으로 찍지 말고, 필요한 것 위주로 작성하라
3. Lombok은 toString을 만들기 귀찮은 개발자들이 성실하게 toString을 구현하도록 유인할 수 있다.

04. clone 재정의는 주의해서 사용하라

배열 copy

int[] a = {1,2,3,4};
int[] b = a; //Shallow copy
b = a.clone(); //deep copy


//Copy시 주의사항
Laptop[] a = {new Laptop("그램 16인치", "삼성")};
Laptop[] b = a.clone();
b[0].setComapny("LG");
//잘 복사한 거 같지만 Object reference value를 참조했기 때문에 a[0] == b[0] 즉 들이 같은 객체를 가리키고 있음




profile
개발블로그

0개의 댓글