java일지

자바 리마인드#14 기본 클래스(1)

리동구 2023. 3. 9. 10:38

2023/03/08

  • 학습내용

1. Object 클래스

 

※ java.lang 패키지

제일 보편적으로 사용하는 String, Integer와 같은 클래스는 java.lang 패키지에 속해 있다.

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

경로 java.base/java/lang 폴더를 보면 java.lang 패키지에서 제공하는 여러 소스 코드를 확인할 수 있다.

 

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

하지만 java.lang 패키지는 컴파일할 때 import java.lang.*; 문장이 자동으로 추가되어 따로 import 하지 않아도 된다.

즉, 개발자가 import문을 직접 쓰지 않아도 java.lang 패키지의 모든 하위 클래스를 참조할 수 있다.

 

 

 

1) 모든 클래스의 최상위 클래스 Object

모든 자바 클래스의 최상위 클래스인 Object는 java.lang 패키지에 속해있고 경로는 java.lang.Object이다.

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

 

보통 상속을 하려면 extends를 입력해야 하지만 Object 클래스는 컴파일 과정에서 extends Object가 자동으로 쓰인다.

개발자가 따로 상속을 하지 않아도 기본적인 클래스들은 Object 클래스를 상속받아 Object의 메서드를 사용하고, 재정의하고, Object형으로 변환할 수도 있는 것이다.

 

 

2) Object 메서드

 

1. toString() 메서드

toString() 메서드는 객체 정보를 문자열(String)로 바꾸어 준다.

String이나 Integer 등 여러 JDK 클래스에는 toString() 메서드가 이미 재정의되어 있다.

 

toString() 메서드는 인스턴스 정보를 문자열로 반환하는 메서드다.

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

 

//toString()메서드 원형

getClass().getName() + '@' + Integer.toHexString(hashCode())

원형을 해석해보면 '클래스 이름@해시 코드 값' 이다.

즉, 클래스의 이름과 16진수 해시 코드 값이 출력된다.

 

예를 들어 Book라는 클래스에서 toString()메서드를 사용해서 출력을 하면 Book@16f65612 이런 식으로 결과가 나온다.

 

 

2. equals() 메서드

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

주소 값이 같다면 같은 인스턴스이다.

 

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

따라서 물리적 동일성(인스턴스의 메모리 주소가 같음)뿐 아니라 논리적 동일성(논리적으로 두 인스턴스가 같음)을 구현할 때도 equals() 메서드를 재정의해서 사용한다.

 

※ Object 클래스의 equals() 메서드

두 인스턴스가 같다는 의미는  두 인스턴스의 주소 값이 같은 경우를 말한다.

즉, 두 변수가 같은 메모리 주소를 가리키고 있다는 뜻이다.

 

 

//equals() 예시1

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

ex) 학생 객체를 구현한 Student 클래스가 있다.

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

이러면 두 변수는 동일한 인스턴스를 가리킨다.

이 때 equals()메서드를 이용해 두 변수를 비교하면 동일하다는 결과가 나온다.

//equals() 예시2

Student studentLee = new Student(100, "이동구");
Student studentLee2 = studentLee;
Student studentSang = new Student(100, "이동구");

ex) 이름과 학번이 동일한 학생을 한 명 더 생성하고 다른 변수(studentSang)가 가리키도록 만들었다.

studentLee, studentLee2가 가리키는 인스턴스와 studenSang이 가리키는 인스턴스는 서로 다른 주소를 가지고 있지만,

저장된 학생의 정보는 같다.

논리적으로는 studentLee, studentLee2와 studenSang을 같은 학생으로 처리하는 것이 맞다.

하지만 물리적 주소가 다르므로 equals 메서드를 사용하면 false로 다른 주소라고 결과가 나온다.

 

 

 

3. hashCode() 메서드

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

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

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

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

 

 

hashCode = hash(key);	//객체의 해시 코드 값(메모리 위치 값)이 반환됨

JAVA에서는 인스턴스를 힙 메모리에 생성하여 관리할 때 해시 알고리즘을 사용한다.

 

Object 클래스의 toString()메서드 원형  getClass().getName() + '@' + Integer.toHexString(hashCode())

여기서 참조 변수를 출력할 때 보면 16진수 숫자 값이 '해시 코드 값'이다.

이 값은 JAVA 가상 머신이 힙 메모리에 저장한 '인스턴스 주소 값'이다.

 

즉, JAVA에서는 두 인스턴스가 같다면  hashCode()메서드에서 반환하는 해시 코드 값이 같아야 한다.

따라서 논리적으로 같은 두 객체도 같은 해시 코드 값을 반환하도록 hashCode()메서드를 재정의해야 한다.

 

 

 

4. clone() 메서드

clone() 메서드는 객체 원본을 유지해 놓고 복사본을 사용한다거나,

기본 틀(prototype)의 복사본을 사용해 동일한 인스턴스를 만들어 복잡한 생성 과정을 간단히 하려는 경우에 사용한다.

protected Object cloen();

clone() 메서드는 Object에 선언되어 있으며, 객체를 복제해 또 다른 객체를 반환해주는 메서드이다.

멤버 변수가 동일한 인스턴스가 다른 메모리에 새로 생성되는 것이다.

 

※ Cloneable 인터페이스

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

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

 

Cloneable 인터페이스를 선언해도 별도로 구현해야하는 메서드는 없다.

이렇게 구현할 메서드가 없는 인터페이스를 마커 인터페이스(marker interface)라고 한다.