본문 바로가기
Language/Java

[Java] Object 클래스

by 계범 2022. 3. 7.

Object클래스란

Object클래스는 모든 클래스의 최고 조상이다.

그래서 Object클래스의 멤버들은 모든 클래스에서 바로 사용 가능하다.

 

Object클래스의 메서드

메서드 설 명
protected Object clone() 객체 자신의 복사본을 반환
public boolean equals(Object obj) 객체 자신과 객체 obj가 같은 객체인지 알려준다.(같으면 true)
protected void finalize() 객체가 소멸될 때 가비지 컬렉터에 의해 자동적으로 호출.
이 때 수행되어야하는 코드가 있을 때 오버라이딩한다(거의 사용안함)
public Class getClass() 객체 자신의 클래스 정보를 담고 있는 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 timeout,int nanos)
다른 쓰레드가 notify()나 notifyAll()을 호출할 때까지 현재 쓰레드를 무한히 또는 지정된 시간(timeout, nanos)동안 기다리게 한다.(timeout은 천 분의 1초, nanos는 10^9분의 1초)

Object타입은 메서드만 가지고 있다.

 

equals(Object obj)

매개변수로 객체의 참조변수를 받아서 비교하여 그 결과를 boolean값으로 전달한다.

// 내부구조
public boolean equals(Object obj){
	return (this == obj);
}
//실제 사용

class EqualsEx1 {
	public static void main(String[] args) {
		Value v1 = new Value(10);
		Value v2 = new Value(10);		

		if (v1.equals(v2)) {
			System.out.println("v1과 v2는 같습니다.");
		} else {
			System.out.println("v1과 v2는 다릅니다.");		
		}

		v2 = v1;

		if (v1.equals(v2)) {
			System.out.println("v1과 v2는 같습니다.");
		} else {
			System.out.println("v1과 v2는 다릅니다.");		
		}
	} // main
} 

class Value {
	int value;

	Value(int value) {
		this.value = value;
	}
}
결과
1. v1과 v2는 다릅니다.
2. v1과 v2는 같습니다.

 

두개의 객체가 실제로 같은 주소를 가진 동일한 인스턴스일때만 true 반환.

1번은 두 객체안의 내용이 같더라도 서로 다른 주소를 가진 객체이므로 false반환.

 

hashCode()

해싱(hashing)기법에 사용되는 '해시함수(hash function)'을 구현한 것이다.

 

해싱은 데이터관리기법 중 하나로, 다량의 데이터를 저장하고 검색하는데 유용하다.

해시함수는 찾고자하는 값을 입력하면, 그 값이 저장된 위치를 알려주는 해시코드를 반환한다.

 

일반적으로 해시코드가 같은 두 객체가 존재하는 것이 가능하지만,

Obejct클래스에 정의된 hashCode메서드는 객체의 주소값으로 해시코드를 만들어 반환하기 때문에

32bit JVM에서는 서로 다른 두 객체가 같은 해시코드를 가질 수 없지만,

62bit JVM에서는 8byte주소값으로 해시코드(4byte)를 만들기 때문에 중복될 수 있다.

 

class HashCodeEx1 {
	public static void main(String[] args) {
		String str1 = new String("abc");
		String str2 = new String("abc");

		System.out.println(str1.equals(str2));
		System.out.println(str1.hashCode());
		System.out.println(str2.hashCode());
		System.out.println(System.identityHashCode(str1));
		System.out.println(System.identityHashCode(str2));
	}
}
true
96354
96354
1910163204
305623748

String클래스는 문자열의 내용이 같으면, 동일한 해시코드를 반환하도록 hashCode메서드가 오버라이딩되어있다.

System.identityHashCode(Object x)를 쓰면 Object클래스의 hashCode메서드처럼 객체의 주소값으로 해시코드를 생성하기 때문에 다른 해시코드값을 반환한다.

 

toString()

인스턴스에 대한 정보를 문자열(String)로 제공할 목적으로 정의된 메서드이다.

 

// 내부구조
public String toString(){
	return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

toString()을 오버라이딩 하지 않는다면,

클래스이름 + 16진수의 해시코드의 문자열을 얻게 된다.

 

그래서 대부분 toString을 오버라이딩하여 쓴다.

 

clone()

자신을 복제하여 새로운 인스턴스를 생성하여 반환해준다.

 

Object클래스에 정의된 clone()은 단순히 인스턴스변수의 값만 복사하기 때문에 참조타입의 인스턴스 변수가 있는 클래스는 완전한 인스턴스 복제가 이루어지지 않는다.

 

예를 들어 배열의 경우, 복제된 인스턴스도 같은 배열의 주소를 갖기 때문에 복제된 인스턴스의 작업이 원래 인스턴스에 영향을 미치게 된다.

 

이런 경우 clone메서드를 오버라이딩해서 새로운 배열을 생성하고 배열의 내용을 복사하도록 해야 한다.

 

Python코드지만 얕은복사 깊은복사 참조

: 2022.01.05 - [CS/Basic] - [Python] 객체복사,shallow copy,deep copy

 

getClass()

자신이 속한 클래스의 Class객체를 반환하는 메서드.

 

public final class Class implement... { // Class 클래스
	...
}​

 

Class객체

  • 이름이 'Class'인 클래스의 객체
  • 클래스의 모든 정보를 담고 있고, 클래스 당 1개만 존재
  • 생성시기: 클래스 파일이 '클래스 로더(ClassLoader)'에 의해 메모리에 올라갈 때, 자동 생성
    • 클래스로더는 프로그램 실행 시 필요한 클래스를 동적으로 메모리에 로드하는 역할
    • 메모리에 기존에 생성된 클래스 객체가 존재하는 확인
    • 존재하면 객체의 참조를 반환, 없으면 클래스패스에 지정된 경로를 따라서 클래스 파일을 읽음
      • 못 찾으면 ClassNotFoundException 발생.
      • 찾으면 클래스 파일 읽어서 Class객체 반환
  • 클래스 파일을 읽어서 사용하기 편한 형태로 저장해 놓은 것이 클래스 객체

 

Class객체를 얻는 법

Class cObj = new Card().getClass(); // 생성된 객체로부터 얻는 방법
Class cObj = Card.class;            // 클래스 리터럴(*.class)로부터 얻는 방법
Class cObj = Class.forName("Card"); // 클래스 이름으로부터 얻는 방법

특히 forName()은 특정 클래스 파일을 올릴 때 주로 사용한다.

ex) 데이터베이스 드라이버를 메모리에 올릴 때

 

Class객체를 이용하면 클래스에 정의된 멤버의 이름이나 개수 등, 클래스에 대한 모든 정보를 얻을 수 있기 때문에 Class객체를 통해서 객체를 생성하고 메서드를 호출하는 등 보다 동적인 코드를 작성할 수 있다.

Card c = new Card(); // new 연산자 이용 생성
Card c = Card.class.newInstance(); // Class객체 이용 생성
newInstance()는 InstantiationException이 발생할 수 있으므로 예외처리 필요.
동적 객체 생성 및 메서드 호출방법에 더 알고싶으면, '리플렉션 API' 검색. ( 추후 공부..)

 

참조

'Java의 정석' 책

댓글