본문 바로가기

자바 기초

자바 Object 클래스, toString, equals - Do it! 자바프로그래밍기초

Object 클래스는 모든 자바 클래스의 최상우 클래스이다. 즉 모든 클래스는 Object 클래스로부터 상속을 받는다.

생각해보면 우리가 클래스를 만들 때 extends Object 코드를 작성한 적이 없는데, 

extends Object가 자동으로 쓰이기 때문이다. 

 

Object 메서드는 여러가지가 있는데, 재정의할 수 있는 메서드도 있고 그렇지 않은 메서드도 있다.

 

 

toString() 메서드

이름처럼 객체 정보를 문자열로 바꾸어 준다. 인스턴스 정보를 문자열로 반환해주고,

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

Object 클래스를 상속받은 모든 클래스는 toString()을 재정의할 수 있고, String이나 Integer 등 여러 JDK 클래스에는 toString() 메서드가 재정의되어 있다.

package object;

class Book {
	int bookNumber;
	String bookTitle;
	
	Book (int booknum, String title) {
		this.bookNumber = booknum;
		this.bookTitle = title;
	}
}

public class ToStringEx {

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

	}

}

위 코드는 책 번호와 제목을 담고 있는 Book 클래스의 인스턴스를 생성하여 그 참조 변수를 출력한다.

System.out.println() 출력문에 참조 변수를 넣으면 인스턴스 정보가 출력되는데,

이 때 자동으로 호출되는 메서드가 toString()이다. 이 toString()은 Book 클래스의 메서드가 아니라 Object 클래스의 메서드이다.

 

toString() 메서드의 원형 : getClass().getName() + '@' + Integer.toHexString(hashCode())

 

String str = new String("test");
System.out.println(str);

Integer i1 = new Integer(100);
System.out.println(i1);

위 코드에서는 test와 100이 출력된다. 왜 두 클래스의 출력 결과는 '클래스 이름@해시 코드 값'이 아닐까 ?

이유는 String과 Integer 클래스는 toString() 메서드가 재정의되어 있기 때문이다. 위에서 말했듯이 toString() 메서드를 미리 재정의한 클래스가 많다.

 

class Book {
	...
    
    @Override
    public String toString() {
    	return bookTitle + ", " + bookNumber;
    }
}
...

이렇게 toString() 메서드를 Book 클래스 안에 재정의 하고 다시 코드를 실행하면 

System.out.println(book1);System.out.println(book1.toStrint()); 모두 개미, 200 이 출력 된다.

이렇게 toString() 메서드를 직접 재정의하면 객체의 참조 변수를 이용해 원하는 문자열을 표현할 수 있다.

 

 

equals() 메서드

원래 기능은 두 인스턴스의 주소 값을 비교하여 boolean 값을 반환해 주는 것이다. 

그런데 서로 다른 주소 값을 가질 때도 같은 인스턴스라고 정의할 수 있는 경우가 있다. 

인스턴스의 메모리 주소가 같은 '물리적 동일성' , 논리적으로 두 인스턴스가 같은 '논리적 동일성'을 구현할 때도

equals() 메서드를 재정의해야 한다.

 

Student studentLee = new Student(100,"이상원");
Student studentLee2 = studentLee; //주소 복사

Student 클래스를 생성하고, 생성된 인스턴스를 가리키는 참조 변수(studentLee)를 다른 변수(studentLee2)에 복사했다.

그러면 두 변수는 동일한 인스턴스를 가리키기 때문에, equals() 메서드를 이용해 비교하면 동일하다는 결과가 나온다.

 

Student studentLee = new Student(100,"이상원");
Student studentLee2 = studentLee; //주소 복사
Student studentSang = new Student(100,"이상원");

위 코드는 studentLee, studentLee2가 가리키는 인스턴스와 studentSang이 가리키는 인스턴스는 서로 다른 주소를 가지고 있지만, 저장된 학생의 정보는 같다. 이 경우 논리적으로는 모두 같은 학생으로 처리하는 것이 맞을 것이다.

 

package object;

public class StringEquals {

	public static void main(String[] args) {
		String str1 = new String("abc");
		String str2 = new String("abc");
		
		System.out.println(str1 == str2); // 두 인스턴스의 주소 값이 같은지 비교
		System.out.println(str1.equals(str2)); // String 클래스의 equals() 메서드 사용.
		                                       // 문자열 값이 같은지 비교
		Integer i1 = new Integer(100);
		Integer i2 = new Integer(100);
		
		System.out.println(i1 == i2);
		System.out.println(i1.equals(i2)); // Interger 클래스의 equals() 메서드 사용
	}                         	           // 인스턴스의 정수 값이 같은지 비교

}

위 코드를 보면 str1와 str2는 서로 다른 인스턴스를 가리키기 때문에 str1 == str2는 false이다.

하지만 String 클래스의 equals() 메서드는 같은 문자열의 경우 true, 그렇지 않은 경우를 false를 반환하도록 재정의되어 있다.

 

class Student {
	...
    
    @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;
    }
}

equals() 메서드를 재정의했다. equals() 메서드는 매개변수는 Object형이다. 비교될 객체가 Object형 매개변수로 전달되면 instanceof를 사용하여 매개변수의 원래 자료형이 Student인지 확인한다. this 학번과 매개변수로 전달된 객체의 학번이 같으면 true를 반환한다.