[김영한의 실전 자바] 중급 1편 - Object 클래스
2024, Oct 11
자바의 기능들을 본질적으로 왜 쓰는지 이해하고 활용하기 위해서 듣겠다
java.lang 패키지 소개
java.lang 패키지의 대표적 클래스들
- Object : 모든 자바 객체의 부모 클래스
- String : 문자열
- Integer, Long, Double : 래퍼 타입, 기본형 데이터 타입을 객체로 만든 것
- Class : 클래스 메타 정보
- System : 시스템과 관련된 기본 기능들을 제공
-> 이건 자바 언어의 기본을 이루는거임 (import 생략이 가능하다)
Object 클래스
자바에서 모든 클래스의 최상위 부모클래스는 Object
클래스이다.
public class Parent {
public void parentMethod() {
System.out.println("Parent.parentMethod");
}
}
- 부모 클래스가 없으면 묵시적으로 Object 클래스를 상속받는다.
public class Parent extends Object {
한 것과 같음
child.toString() 메서드를 호출하였을 때 실행 결과
Child
에서toString()
을 찾음- 없으면 부모 타입인
Parent
에서 찾음 - 없으면 부모 타입인
Object
에서 찾음 (Object
에는toString()
이 있음!) - 있으면 호출~
자바에서 Object 클래스가 최상위 부모 클래스인 이유
- 공통 기능 제공 -> 일관성을 가짐
- 다형성의 기본 구현
Object 다형성
Object 다형성의 한계
public class ObjectPolyExample1 {
public static void main(String[] args) {
Dog dog = new Dog();
Car car = new Car();
action(dog);
action(car);
}
private static void action(Object obj) {
//컴파일 오류
// obj.sound(); //Object는 sound()가 없다.
// obj.move(); // Object는 move()가 없다.
//호출하는 방법 -> 객체에 맞는 다운캐스팅 필요
if (obj instanceof Dog dog) {
dog.sound();
} else if (obj instanceof Car car) {
car.move();
}
}
}
-
obj.sound()
를 호출하면 Object에서sound()
를 찾는다. -> 없으면 부모로 올라가는데, Object가 최종부모이니 올라갈 수 없음 -> 오류발생 - 다운캐스팅을 하게되면 Dog 에서
sound()
를 찾아서 호출함. - Object를 통해 전달 받은 객체를 호출하려면 다운캐스팅 과정이 필요한 한계가 있음
- 다형성을 제대로 참조하려면 다형적 참조 + 메서드 오버라이딩을 함께 사용해야함.
- Object에선 메서드 오버라이딩을 활용할 수 없음
Object 배열
public class ObjectPolyExample2 {
public static void main(String[] args) {
Dog dog = new Dog();
Car car = new Car();
Object object = new Object();
Object[] objects = {dog, car, object};
size(objects);
}
private static void size(Object[] objects) {
System.out.println("전달된 객체의 수는: " + objects.length);
}
}
size()
메서드는 Object 타입만 사용하기 때문에, 자바를 쓰는 어떤 곳에서든 사용 가능함
Object가 없다면?
- 모든 객체를 받을 수 있는 메서드를 만들 수 없음
- 모든 객체를 저장할 수 있는 배열을 만들 수 없음
MyObject
같은 클래스를 직접 만들어서 쓸 수는 있지만, 모든 개발자가 만들어서 쓰는건 호환성이 떨어진다.
toString()
- 객체의 정보를 문자열 형태로 제공함.
- 디버깅과 로깅에서 유용하게 사용함
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
- Object가 제공하는
toString()
메서드는 기본적으로 패키지를 포함한 객체의 이름과 참조값을 제공한다.
public class ToStringMain1 {
public static void main(String[] args) {
Object object = new Object();
String string = object.toString();
//결과가 같게 나옴 - java.lang.Object@10f87f48
System.out.println(string);
System.out.println(object);
}
}
- 어떻게 두개가 결과값이 똑같을까~
println()
-> 여기서obj.toString()
을 호출하고있음
toString() 오버라이딩
- 보통 오버라이딩으로 재정의하여 유용한 정보를 제공함~
public class ObjectPrinter {
public static void print(Object obj) {
String string = "객체 정보 출력: " + obj.toString();
System.out.println(string);
}
}
public class ToStringMain2 {
public static void main(String[] args) {
Car car = new Car("Model Y");
Dog dog1 = new Dog("멍멍이1" , 2);
Dog dog2 = new Dog("멍멍이2", 5);
System.out.println("1. 단순 toString 호출");
System.out.println(car.toString());
System.out.println(dog1.toString());
System.out.println(dog2.toString());
System.out.println("2. println 내부에서 toString 호출");
System.out.println(car);
System.out.println(dog1);
System.out.println(dog2);
System.out.println("3. Object 다형성 활용");
ObjectPrinter.print(car);
ObjectPrinter.print(dog1);
ObjectPrinter.print(dog2);
}
}
- 이렇게 쓰는 것도 결과가 똑같이 나옴
- 인텔리제이에선
toString()
자동생성도 가능~
- Object에서
toString()
을 찾음 - 자식에 오버라이딩된 메서드가 있는지 찾아보고 있으면 자식에서 출력~
(참고) 객체의 참조값을 출력하는 방법
Integer.toHexString(System.identityHashCode(dog1));
- HashCode를 16진수로 변환하는거임
equals()
1. 동일성과 동등성
- 동일성(Identity) :
==
연산자를 사용해서 참조가 동일한 객체를 가리키는지 확인 - 동등성(Equality) :
equals()
메서드를 사용하여 두 객체가 논리적으로 동등한지 확인
UserV1 userV1 = new UserV1("id-100");
UserV1 userV2 = new UserV1("id-100");
System.out.println("identity = " + (userV1 == userV2)); // false
System.out.println("equality = " + (userV1.equals(userV2))); // false
- 둘 다 false임
- Object에서 기본으로 제공하는
equals()
는==
으로 동일성 비교를 제공함 -
public boolean equals(Object obj) { return (this == obj); }
- Object에서 기본으로 제공하는
-> 동등성을 비교하고 싶으면 메서드를 재정의해서 사용해야한다.
2. 구현
@Override
public boolean equals(Object obj) {
UserV2 user = (UserV2) obj;
boolean result = id.equals((user.id));
return result;
}
- 이렇게 하고 다시 실행하면 equals 비교는 true임
정확한 equals() 구현
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
UserV2 userV2 = (UserV2) o;
return Objects.equals(id, userV2.id);
}
- equals() 메서드를 구현할 때 지켜야 하는 규칙 - 반사성, 대칭성, 추이성, 일관성, null에 대한 비교
정리
Object의 나머지 메서드
clone()
-> 객체를 복사hashCode()
-> equals()와 hashCode()는 종종 함께 사용.getClass()
-> Class 정보를 알 수 있음notify()
… -> 멀티스레드 관련 메서드