상속과 다형성 - 6. 최상위 클래스 Object

Ⅵ. 최상위 클래스 Object

1. Object 클래스 : 모든 자바 클래스의 부모 클래스

 - 자바의 모든 클래스는 Object의 자식클래스 = 자바의 모든 클래스는 Object의 메소드를 가짐

 

2. Object 메소드 : toString ( )

 - 객체의 정보 패키지.클래스명@해쉬코드

 - 일반적으로 오버라이딩해서 사용

// Example1
// Object 클래스의 toString() 메소드
package sample;

class A { 			//extends Object (컴파일러에 의해서 자동추가)
	int a = 3;
	int b = 4;
}

class B {			// toString() overriding
	int a = 3;
	int b = 4;

	public String toString() {		
		return "필드값(a, b) =" + a +" " +b;
	}	
}
public class Main {
	public static void main(String[] args) {
		// 1. 객체 생성
		A a = new A();
		B b = new B();
		
		// 2. 메소드 호출
        
		// hashcode를 16진수로 표현
		System.out.printf("%x\n", a.hashCode());	// 379619aa
        
		// toString()메소드는 생략시 자동 추가
		System.out.println(a.toString());		// day10.A@379619aa
        
		System.out.println(b);				// 필드값(a, b) =3 4
	}
}

 

// Example2
package sample;

class Dog {
	@Override
	public String toString() {
		return super.toString();
	}
	
}

public class Main {
	public static void main(String[] args) {
		System.out.println(new Dog().toString());	// sample.Dog@1c4af82c
	}
}

 

// Example3
package sample;

class Dog {
	String name;
	Dog(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return this.name;
	}
	
}

public class Main {
	public static void main(String[] args) {
		System.out.println(new Dog("순돌이").toString());	// 순돌이
	}
}

 

// Example4
package sample;

class Dog {
	String name;
	Dog(String name) {
		this.name = name;
	}
	
	@Override
	public String toString() {
		return this.name;
	}
	
}

public class Main {
	public static void main(String[] args) {
		Dog soondol = new Dog("순돌이");
		
		// toString 메소드의 반환값은 참조 변수로 반환되기도 함
		System.out.println(soondol);	// 순돌이
	}
}

 

3. Object 메소드 : equals( )

 - 객체의 stack 메모리 값(번지) 비교 (비교연산자 '==' 와 동일한 결과)

    ※ 참조자료형 간의 비교는 주소를 비교 (a == b) (문자열은 예외)

    ※ 참조자료형 간의 값을 비교하는 방법 : equals( ) 

        → equals( )를 오버라이딩하면, 비교 방법을 직접 정할 수 있음

// Example1
// Object 클래스의 equals(.) 메소드
package sample;

class A {
	String name;
	A(String name) {
		this.name = name;
	}
}
class B {
	String name;
	B(String name) {
		this.name = name;
	}
	@Override
	public boolean equals(Object obj) {
		if(this.name == ((B)obj).name) {
			return true;
		} else { 
			return false;
		}
	}	
}
public class Main {
	public static void main(String[] args) {		
		A a1 = new A("안녕");
		A a2 = new A("안녕");
		
		System.out.println(a1 == a2);		// false
		System.out.println(a1.equals(a2));	// false
		
		
		B b1 = new B("안녕");
		B b2 = new B("안녕");
		
		System.out.println(b1 == b2);		// false
		System.out.println(b1.equals(b2));	// true		
	}
}

 

// Example2-1
package sample;

class INum{			// 숫자 하나를 필드로 갖는 클래스
	private int num;	// private : 정보 은닉
	INum(int num) {
		this.num = num;
	}
}

public class Main {
	public static void main(String[] args) {
		INum num1 = new INum(20);
		INum num2 = new INum(20);
		
		// 메모리 주소 비교
		System.out.println(num1 == num2);	// false
		
		// 메모리 주소 비교
		System.out.println(num1.equals(num2));	// false
		
	}
}

 

// Example2-2
package sample;

class INum{			// 숫자 하나를 필드로 갖는 클래스
	private int num;	// private : 정보 은닉
	INum(int num) {
		this.num = num;
	}
	
	// 객체가 가지고 있는 값이 같아야만 같은 것으로 인정하게 만듦
	public boolean equals(Object obj) {
		if(this.num == ((INum)obj).num) {	// ((INum)obj).num 하여 Object를 INum으로 다운캐스팅
			return true;
		} else {
			return false;
		}
	}	// num1과 num2의 값을 equals로 비교하여 추출
}

public class Main {
	public static void main(String[] args) {
		INum num1 = new INum(20);
		INum num2 = new INum(20);
		
		// 메모리 주소 비교
		System.out.println(num1 == num2);	// false
		
		// 메모리 주소 비교
		System.out.println(num1.equals(num2));	// true;
	}
}

 

4. Object 메소드 : hashcode( )

    ※ 해시 코드 : 객체가 가진 고유한 값(id) (= 해시 알고리즘에 의해 생성된 정수 값)

 - 고유한 값을 정의할 수 있음

 - 객체의 hashCode() 값 리턴. HashTable, HashMap 등의 동등비교에 사용

 - (STEP1. hashcode ( )) 일치 + (STEP2. equals( )) true → 동일객체

 ※ HashMap : 중복되지 않는 데이터를 저장하는 매체

// Example1
package sample;

import java.util.HashMap;	// 자바 내장 참조 자료형

public class Main {
	public static void main(String[] args) {
		
		// HashMap : 중복되지 않는 데이터를 저장하는 매체	<= 키가 중복되지 않음 (값은 중복 가능)
		// 데이터 하나당 두개의 정보를 가짐
		HashMap<String, String> aaa = new HashMap<>();
		
		// 데이터 중 첫 번째 정보를 키(Key)라 하고, 두 번째 정보를 value라 함
		aaa.put("name1", "tom");
		aaa.put("name2", "tom");
		aaa.put("name3", "tom");
        
		System.out.println(aaa.get("name1"));	// tom
	}
}

 

// Example2
package sample;

import java.util.HashMap;		// 자바 내장 참조 자료형

class MyNum {
	int num;
	MyNum(int num) {
		this.num = num;
	}
	@Override
	public int hashCode() {		// 중복을 확인하는 hashCode()
		return this.num;
	}	// 이렇게 하면 좀 더 빠르게 중복 여부 확인 가능
	@Override
	public boolean equals(Object obj) {
		if(this.num == ((MyNum)obj).num) {
			return true;
		} else {
			return false;
		}
	}
}

public class Main {
	public static void main(String[] args) {
		
		// HashMap : 중복되지 않는 데이터를 저장하는 매체	<= 키가 중복되지 않음 (값은 중복 가능)
		// 데이터 하나당 두개의 정보를 가짐
		HashMap<MyNum, String> bbb = new HashMap<>();
		bbb.put(new MyNum(1), "data");
		bbb.put(new MyNum(1), "data");
		bbb.put(new MyNum(1), "data");
		bbb.put(new MyNum(1), "data");	// 이렇게 하면 중복이다라는 것을 발견하여, 중복을 막음
		
		System.out.println(bbb);	// {day10.MyNum@1=data}
	}
}

 

// Example3
package sample;

import java.util.*;	// 자바로부터 제공되는 기능을 가져다 씀

class NumBox {
	int num;
	NumBox(int n){
		this.num = n;
	}
	public int hashCode() {
		// 0, 1, 2 중 하나의 숫자가 나의 해시코드
		// 해시맵에서 비교할 떄는 해시코드가 같은 것끼리 비교
		return this.num % 3;
	}
	// 이퀄스를 오버라이딩하면, 비교 방식도 내가 정할 수 있음
	public boolean equals(Object obj) {
		if (((NumBox)obj).num == this.num) {
			return true;
		} else {
			return false;
		}
	}
}

public class Main {
	public static void main(String[] args) {
		HashMap<NumBox, String> sample = new HashMap<>();
		
		sample.put(new NumBox(1), "???");
		sample.put(new NumBox(1), "!!!");
		
		System.out.println(sample);
	}
}