[Java] Object와 Overriding

가을·2022년 11월 4일
0

Java

목록 보기
1/2
post-thumbnail

Overriding

  • 부모 클래스로부터 상속받은 메소드의 내용을 변경하는 것

오버라이딩의 조건

  • 부모 클래스의 메서드와 이름이 같아야 한다
  • 부모 클래스의 메서드와 매개변수가 같아야 한다
  • 반환타입이 같아야 한다
  • 부모 클래스의 메서드보다 접근 제어자를 좁은 범위로 변경할 수 없다
  • 부모 클래스의 메서드보다 예외를 많이 선언할 수 없다
  • 인스턴스메서드를 static메서드로 또는 그 반대로 변경할 수 없다

부모 클래스에서 정의된 static메서드를 자식 클래스에서 똑같은 이름의 static메서드로 정의한다고 해서 오버라이딩은 아니다. 단지 각 클래스에서 별개의 static메서드를 정의한 것일 뿐이다.


Object 클래스

  • 모든 클래스의 최상위 클래스

1. 대표적인 메소드

protected Object clone() 		  // 객체 자신의 복사본을 반환
public boolean equals(Object obj) // 객체 자신과 객체 obj가 같은 객체인지 확인
public Class getClass() 		  // 객체 자신의 클래스 정보를 가지고 있는 Class 인스턴스를 반환
public int hashCode() 			  // 객체 자신의 해시코드를 반환 
public String toString()          // 객체 자신의 정보를 문자열로 반환
public void notify()              // 객체 자신을 사용하려고 기다리는 쓰레드를 하나만 깨움 
public void notifyAll()           // 객체 자신을 사용하려고 기다리는 쓰레드 모두 깨움 
public void wait()                // 다른 쓰레드가 notify()|notifyAll()를 호출할 때까지 대기 

1.1 예제

public class Student {

    int id;

    public static void main(String[] args) {
        Student s1 = new Student();
        Student s2 = new Student();
        s1.id = 123456;
        s2.id = 123456;

        if(s1.equals(s2))
            System.out.println("s1 == s2");
        else
            System.out.println("s1 != s1");   
            
        System.out.println(s1.hashCode());
        System.out.println(s2.hashCode());
        System.out.println(s1.toString());
        
        // 실행결과
        // s1 != s2
        // 747464370
		// 1513712028
		// Student@2c8d66b2
    }
}

위의 실행결과를 정리하자면 결론적으로 객체 s1과 객체 s2는 같지 않다. 즉, 객체가 저장되어있는 메모리 주소가 같지 않다는 것이다. 따라서 주소값으로 만드는 해시코드도 같지 않다.

2. equals(Object obj)

Object 클래스에 정의되어 있는 equals 메소드
public boolean equals(Object obj) {
        return (this == obj);
}
  • 객체의 참조변수를 받아 값을 비교해 그 결과를 boolean값으로 반환
  • 만약 주소값이 아닌 Student인스턴스가 가지고 있는 id값을 비교하도록 하고 싶다면 함수를 Overriding하면 된다.
재정의된 equals 메소드
@Override
public boolean equals(Object obj) {
	return (this.id == ((Student) obj).id);
}

3. hashCode()

  • Object클래스에 정의된 hashCode 메서드는 객체의 주소값으로 해시코드를 만들어 반환
  • 32 bit JVM에서는 서로 다른 객체는 절대 같은 해시코드를 가질 수 없으나, 64 bit JVM에서는 8 byte 주소값으로 해시코드(4 byte)를 만들어 중복 가능성 존재

클래스의 인스턴스변수 값으로 객체의 같고 다름을 판단해야 할 경우, equals메서드 뿐 만아니라 hashCode메서드도 Overriding 해야 한다.

String 클래스는 문자열의 내용이 같으면 동일한 해시코드를 반환하도록 hashCode메서드가 오버라이딩 되어 있다. 반면에 System.identityHashCode(Object x)는 Object클래스처럼 객체의 주소값으로 해시코드를 생성해 모든 객체에 대해 항상 다른 해시코드값을 반환한다.

4. toString()

인스턴스 내부의 값 정보를 알고 싶다면 재정의를 통해 toString메소드를 사용한다.

Object 클래스에 정의되어 있는 toString 메소드
public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
방법 1. 코드를 통한 재정의
@Override
public String toString() {
	return "Student [id = " + id + "]";
}
방법 2. Spring에서 Lombok을 통한 @ToString
@ToString
public class Student {

    int id;
    ... 생략
}

@ToString 을 통해 따로 코드로 재정의하지 않아도 편리하게 재정의할 수 있다.

참고 : 자바에서 toString 메소드는 기본적으로 각 API 클래스마다 자체적으로 오버라이딩을 통해 재정의되어있다. ex) String, Class, Arrays ...

참고: toString()과 String.valueOf() 모두 Object 클래스의 값을 String 클래스로 변환한다. Object가 null인 경우 toString()는 Null PointerException을 발생시키지만 String.valueOf()는 null 값을 반환한다.

결론

  • 위와 같이 학번 같다면 같은 객체로 보고 싶은 것처럼 객체를 어떠한 기준으로 비교할 것인지에 따라 equals()와 hashCode()를 재정의할 것인지 결정할 수 있다.
  • 객체의 내부 값의 정보를 문자열로 출력하고 싶다면 toString()를 재정의 해야 한다.
  • 따라서 개발자가 어떠한 기능을 구현할지에 따라 상황에 맞게 메소드를 재정의하는 습관을 들여야한다.
profile
코린이

0개의 댓글