각진 세상에 둥근 춤을 추자

[Java] Object 클래스 본문

Java

[Java] Object 클래스

circle.j 2022. 9. 23. 19:18

java.lang 패키지

 

자바 프로그램을 구현하기 위해 사용하는 클래스는 java.lang 패키지에 속해 있다. 

예를 들면 String 클래스의 전체 이름은 java.lang.String이고, Integer 클래스의 전체 이름은 java.lang.Integer이다.

이와 같이 java.lang 패키지에는 기본적으로 많이 사용하는 클래스들이 포함되어 있다. 

 

 

자바 프로그래밍에서 외부 패키지에 선언한 클래스를 사용할 때는 import문으로 클래스가 어느 패키지에 속해 있는지 선언해야 한다.

java.lang 패키지에는 대표적으로 String 클래스도 속해있다.

하지만 실제 String 클래스를 쓰면서 import java.lnag.String; 이라는 문장을 쓰지 않는다.

왜냐하면 java.lang 패키지는 컴파일 할 때 import.java.lang.*; 문장이 자동으로 추가되기 때문이다.

 

 

Object 클래스

 

java.lang 패키지에 속해있는 클래스 중 java.lang.Object 클래스는 가장 최상위 클래스이다. 

즉, Object 클래스로부터 모든 클래스는 상속 받는다. 

하지만 실제 클래스를 작성시, Object 클래스를 상속받는 코드를 작성하지 않는다. 

이 또한 컴파일 과정에서 Object 클래스를 상속받는다는 뜻의 extends Object가 자동으로 쓰인다. 

 

메서드 설명
String toString() 객체를 문자열로 표현하여 반환한다.
재정의하여 객체에 대한 설명이나 특정 변수 값을 반환할 수 있다.
boolean equals(Object obj) 두 인스턴스가 동일한지 여부를 반환한다.
재정의하여 논리적으로 동일한 인스턴스임을 정의할 수 있다.
int hashCode() 객체의 해시 코드 값을 반환한다.
Object clone() 객체를 복제하여 동일한 멤버 변수 값을 가진 새로운 인스턴스를 생성한다.
Class getClass() 객체의 Class 클래스를 반환한다.
void finalize() 인스턴스가 힙 메모리에서 제거될 때 가비지 컬렉터(GC)에 의해 호출되는 메서드이다.
네트워크 연결 해제, 열려 있는 파일 스트림 해제 등을 구현한다.
void wait() 멀티스레드 프로그램에서 사용하는 메서드이다.
스레드를 '기다리는 상태' (non runnable)로 만든다.
void notify() wait() 메서드에 의해 기다리고 있는 스레드를 실행 가능 한 상태(runnable)로 가져온다. 

 


(1) toString() 메서드

 

Object 클래스에서 기본으로 제공하는 toString() 메서드는 객체 정보를 문자열(String)로 바꾸어 준다.

toString() 메서드의 원형은 생성된 인스턴스의 클래스 이름과 주소 값을 보여 준다. 

 

예제를 통해 toString() 메서드를 이해해 본다. 

 

package ch11_1;

class Book {
	
	int bookNumber;
	String bookTitle;
	
	// 책 번호와 제목을 매개변수로 입력받는 생성자
	Book (int bookNumber, String bookTitle){
		this.bookNumber = bookNumber;
		this.bookTitle = bookTitle;
	}
	
}

public class ToStringEx {
	public static void main(String[] args) {
		
		Book book1 = new Book(200,"개미");
		
		// 인스턴스 정보(클래스 이름, 주소 값)
		System.out.println(book1);
		
		// toString() 메서드: 인스턴스 정보(클래스 이름, 주소 값)을 보여준다.
		System.out.println(book1.toString());
		
	}
}

toString 메서드를 이용해 출력을 하면 인스턴스 정보인 클래스 이름과 주소 값을 알 수 있다.

이때 주소 값은 해시 코드 값으로 16진수이다. 

 

toString 메서드를 이용하여 Book 클래스의 "책 이름, 책 번호"를 출력할 수도 있다. 

즉, Book 클래스에서 toString() 메서드를 직접 정의한다. 

 

package ch11_1;

class Book {
	
	int bookNumber;
	String bookTitle;
	
	// 책 번호와 제목을 매개변수로 입력받는 생성자
	Book (int bookNumber, String bookTitle){
		this.bookNumber = bookNumber;
		this.bookTitle = bookTitle;
	}
	
	// toString() 메서드 재정의 
	@Override
	public String toString() {
		return bookTitle + ", " + bookNumber;
	}
	
}

public class ToStringEx {
	public static void main(String[] args) {
		
		Book book1 = new Book(200,"개미");
		
		System.out.println(book1);
		System.out.println(book1.toString());
		
	}
}


(2) equals() 메서드

 

객체가 동일한 값을 가지고 있는지 검사하기 위해서는, == 연산자가 아닌 equals()메소드를 재정의하여서 사용해야 한다.

 

예제를 통해 equals() 메서드를 이해해 본다. 

 

package ch11_1;

class Student {
	
	int studentId;
	String studentName;
	
	public Student(int studentId, String studentName) {
		this.studentId = studentId;
		this.studentName = studentName;
	}
	
	public String toString() {
		return studentId + ", " + studentName;
	}
	
}

public class EqualsTest {
	public static void main(String[] args) {
		
		Student stu1 = new Student(100, "이자바");
		
		// 주소 복사
		Student stu2 = stu1;
		Student stu3 = new Student(100, "이자바");
		
		// (1) == 연산자로 비교 했을 때 
		if (stu1 == stu2) {
			System.out.println("stu1 과 stu2의 주소는 같습니다.");
		} 
		else { 
			System.out.println("stu1 과 stu2의 주소는 다릅니다.");
		}
		
		// (2) equals() 메서드로 비교했을 때
		if (stu1.equals(stu2)) {
			System.out.println("stu1과 stu2는 동일합니다.");
		}
		else {
			System.out.println("stu1과 stu2는 동일하지 않습니다.");
		}
		
		// (1) == 연산자로 비교 했을 때 
		if (stu2 == stu3) {
			System.out.println("stu2 과 stu3의 주소는 같습니다.");
		} 
		else { 
			System.out.println("stu2 과 stu3의 주소는 다릅니다.");
		}
				
		// (2) equals() 메서드로 비교했을 때
		if (stu2.equals(stu3)) {
			System.out.println("stu2과 stu3는 동일합니다.");
		}
		else {
			System.out.println("stu2과 stu3는 동일하지 않습니다.");
		}
		
	}
}

 

 

equals() 메서드를 Student 클래스에서 재정의 할 수 있다.

package ch11_1;

class Student {
	
	int studentId;
	String studentName;
	
	public Student(int studentId, String studentName) {
		this.studentId = studentId;
		this.studentName = studentName;
	}
	
	public String toString() {
		return studentId + ", " + studentName;
	}
	
	@Override
	public boolean equals(Object obj) {
		if (obj instanceof Student) {
			Student std = (Student)obj;
			if(this.studentId == std.studentId)
				return true;
			else return false;
		}
		return false;
	}
	
}

public class EqualsTest {
	public static void main(String[] args) {
		
		Student stu1 = new Student(100, "이자바");
		
		// 주소 복사
		Student stu2 = stu1;
		Student stu3 = new Student(100, "이자바");
		
		// (1) == 연산자로 비교 했을 때 
		if (stu1 == stu2) {
			System.out.println("stu1 과 stu2의 주소는 같습니다.");
		} 
		else { 
			System.out.println("stu1 과 stu2의 주소는 다릅니다.");
		}
		
		// (2) equals() 메서드로 비교했을 때
		if (stu1.equals(stu2)) {
			System.out.println("stu1과 stu2는 동일합니다.");
		}
		else {
			System.out.println("stu1과 stu2는 동일하지 않습니다.");
		}
		
		// (1) == 연산자로 비교 했을 때 
		if (stu2 == stu3) {
			System.out.println("stu2 과 stu3의 주소는 같습니다.");
		} 
		else { 
			System.out.println("stu2 과 stu3의 주소는 다릅니다.");
		}
				
		// (2) equals() 메서드로 비교했을 때
		if (stu2.equals(stu3)) {
			System.out.println("stu2과 stu3는 동일합니다.");
		}
		else {
			System.out.println("stu2과 stu3는 동일하지 않습니다.");
		}
		
	}
}

 


(3) hashCode() 메서드 

 

해시(hash)는 정보를 저장하거나 검색할 때 사용하는 자료 구조이다. 

정보를 어디에 저장할 것인지, 어디서 가져올 것인지 해시 함수를 사용하여 구현한다.

해시 함수는 객체의 특정 정보(키 값)을 매개변수 값으로 넣으면 그 객체가 저장되어야 할 위치나 저장된 해시 테이블 주소(위치)를 반환한다. 

따라서 객체 정보를 알면 해당 객체의 위치를 빠르게 검색할 수 있다. 

index = hash(key)

index - 저장 위치

hash - 해시 함수

key - 객체 정보

 

예제를 통해 hashCode() 메서드를 이해해 본다.

 

package ch11_1;

public class HashCodeTest {
	public static void main(String[] args) {
		
		String str1 = new String("abc");
		String str2 = new String("abc");
		
		//abc 문자열의 해시 코드 값 출력
		System.out.println(str1.hashCode());
		System.out.println(str2.hashCode());
		
		Integer i1 = new Integer(100);
		Integer i2 = new Integer(100);
		
		// Integer(100)의 해시 코드 값 출력
		System.out.println(i1.hashCode());
		System.out.println(i2.hashCode());
		
	}
}

 


(4) clone() 메서드

객체 원본을 유지한 채 복사본을  사용한다거나, 기본 틀(prototype)의 복사본을 사용해 동일한 인스턴스를 만들어 복잡한 생성 과정을 간단히 하려는 경우,

clone() 메서드를 사용한다. 

protected Object clone();

clone() 메서드를 사용하려면 객체를 복제해도 된다는 의미로 클래스에 Cloneable 인터페이스를 구현해야 한다.

만약 clone() 메서드만 정의하고 Cloneable 인터페이스를 명시하지 않으면 clone() 메서드를 호출할 때 오류가 발생한다. 

 

package ch11_1;

// 원점을 의미하는 Point 클래스
class Point{
	int x;
	int y;
	
	Point(int x, int y){
		this.x = x;
		this.y = y;
	}
	
	public String toString(){
		return "x = " + x + ", y= " + y;
	}
}

// Cloneable 인터페이스 구현
class Circle implements Cloneable{
	Point point;
	int radius;

	Circle (int x, int y, int radius){
	this.radius = radius;
	point = new Point(x,y);
	}

	public String toString() {
		return "원점은 " + point + "이고, 반지름은 " + radius + "입니다.";
	}
	
	// clone() 메서드 사용시 발생할 수 있는 오류를 예외 처리한다. 
	@Override
	public Object clone() throws CloneNotSupportedException{
		return super.clone();
	}
	
}

public class ObjectCloneTest {
	public static void main(String[] args) throws CloneNotSupportedException {
		
		Circle c1 = new Circle(10, 20, 30);
		
		// clone() 메서드를 사용해 c1 인스턴스를 copyc1에 복제한다.
		Circle copyc1 = (Circle) c1.clone();
		
		System.out.println(c1);
		System.out.println(copyc1);
		System.out.println(System.identityHashCode(c1));
		System.out.println(System.identityHashCode(copyc1));
		
	}
}

 

'Java' 카테고리의 다른 글

[Java] 문자열 ↔︎ char 배열  (0) 2022.09.24
[Java] String 클래스  (0) 2022.09.23
[Java] 인터페이스와 다형성  (0) 2022.09.23
[Java] 인터페이스  (0) 2022.09.21
[Java] final 예약어  (0) 2022.09.21