🏃♂️ 들어가기 앞서..
본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕
*해당 교재의 목차 순서와 구성을 참고하여 작성하며
각 내용마다 부족할 수 있는 내용이나 개인적으로 궁금한 점은
추가적인 검색을 통해 채워나갈 예정입니다.
" java.lang
패키지 "는 가장 기본이 되는 클래스들을 포함하고 있는만큼
import문 없이 사용할 수 있다.
가장 기본이 되는만큼
자주 사용되기 때문에 해당 패키지의 여러 클래스 중
중요한 몇 가지만 알아보도록 하자.
( 별개로 자주 쓰이는 키워드들도 따로 다룰 예정이다.. )
Object
클래스이 Object 클래스는 상속에 대해 알아볼 때 자주 볼 수 있었는데
해당 클래스는
모든 클래스의 최고 조상이고
Object클래스의 멤버들은 모든 클래스에서 사용 가능하다.
( 오직 " 11개의 메서드 "만을 가지고 있음)
Object클래스 메서드 | 설명 |
---|---|
protect Object clone() | 객체 자신의 복사본을 반환 ( public 으로 오버라이딩 해줘야함. ) |
public boolean equals( Object obj ) | 객체 자신 - 객체 obj가 같은 객체인지 알려준다. ( 같으면 true ) |
protect void finalize() | (거의 사용 X) " 객체가 소멸될 때 " 가비지 컬렉터에 의해 자동적으로 호출 ( public 으로 오버라이딩 해줘야함. ) |
public Class getClass() | 객체 자신의 클래스 정보를 담고있는 Class 인스턴스 반환 |
public int hashCode() | 객체 자신의 해시코드 반환 |
public String toString() | 객체 자신의 정보를 문자열로 반환 |
public void notify() | 객체 자신을 사용하려고 기다리는 쓰레드(Thread)를 " 하나만 " 깨움. |
public void notifyAll() | 객체 자신을 사용하려고 기다리는 " 모든 " 쓰레드(Thread)를 깨움. |
public void wait() public void wait( long timeout ) public void wait(long timeout, int nanos) | 위 notify메서드들을 다른 쓰레드가 호출할 때까지 현재 쓰레드를 " 무한히 / 지정된 시간 (timeout , nanos)동안 " 기다리게 한다. ( timeout : 1/1000 초 , nanos : 1/10^9 초 ) |
equals()
메서드/*
실제 Object클래스에 정의되어 있는 equals 메서드
*/
public boolean equals(Object obj) {
return (this==obj);
}
매개변수로
" 객체의 참조변수 "를 받아서 비교한 후,
boolean값 결과를 반환한다.
단,
주의해야할 점은
이 equals()
메서드는
엄밀히 말하자면
" 두 인스턴스의 주소값(참조변수 값)으로 비교 "를 하기 때문에
보이는 값은 같을지라도
결과가 false가 나올 수도 있다.
❓
equals()
오버라이딩해당 메서드는 두 주소값만을 비교하고 이외에 판단하지 않는다.
그래서
주소값이 아닌 값을 비교할 수 있도록 하기위해
오버라이딩이 필요하다.
즉,주소가 아닌
객체에 저장된 내용을 비교하도록 변경하는 것이다.class Test { public static boid main(String[] args) { Value v1 = new Value(10) ; Value v2 = new Value(10) ; if (v1.equals(v2)) System.out.println( " 둘이 똑갔습니다."); esle System.out.println( " 둘이 다르다. "); } class Value { int value ; Value(int value) { this.value = value ; } // Object의 equals() 오버라이딩 // 형전환 전엔 반드시 instanceof 로 확인 public boolean equals(Object obj) { if(!(obj instanceof Value)) return false ; // Value v = (Value)obj ; // value로 형변화 return this.value == v.value ; }} }
하나 더 살펴보자면
class Person { long id; public boolean equals(Object obj) { //equals() 오버라이딩 _ id값을 비교하도록 만듦 if(obj instanceof Person) return id == ((Person)obj).id // Object타입이기 때문에 Person타입으로 형변환하여 id값 참조 else return false ; } Person(long id) { //주민번호를 매개변수로 받는 this.id = id; } } class Program { public static void main(String[] args) { Person p1 = new Person(8008081111222L); Person p2 = new Person(8008081111222L); /* 만약 오버라이딩을 하지 않았다면 p1의 객체 주소값과 p2의 객체 주소값을 비교하게되서 false가 반환됨. */ if(p1.equals(p2)) // 오버라이딩해서 주소값을 비교하는것이 아닌 id를 비교하게됨. System.out.println("같은 사람") ; // 서로 같은 8008081111222 값의 메모리 주소를 가지고있기 때문에 true가 출력된다. else System.out.println("다른 사람") ; } }
hashCode()
메서드" 해싱(hashing) 기법 "에 사용되는 【해시함수(hash function)】을 구현한 것
(데이터 관리 기번 중 하나 _ 다량의 데이터 저장&검색에 유용)
Object클래스의hashCode()
는 " 객체의 주소를 int로 변환해서 반환 "
정확히 말하자면
객체의 주소값을 이용해서 해시코드를 만들어 반환하는 것이다.
따라서
" 서로 다른 두 객체는 절대 같은 해시코드를 가질 수 없다 "는 특징이 있다.
이 특징을 통해
" 객체의 같고 다름을 확인해야하는 경우 "
같은 객체라면
hashCode()
의 결과값, 해시코드가 같아야 한다는 것 을 활용해야 한다.
그렇기 때문에
앞서 알아본 equals()
메서드를 오버라이딩 한다면
hashCode()
메서드도 오버라이딩해서 사용해야 한다.
( 오버라이딩을 하지않으면 본래 정의된 대로 모든 객체가 다른 해시코드를 갖게 됨. ▶ equals는 true가 나오는데 hashCode가 다르면 모순 )
단,
String 클래스는 " 문자열 내용이 같으면 "
동일한 해시코드를 반환하도록 본 메서드가 오버라이딩되어 있다.
아래 코드를 살펴보면 알 수 있지만
String클래스 객체인 str1
과 str2
의 해시코드는 같지만
서로 다른 객체라는 것을 알 수 있다.
String str1 = new String("abc");
String str2 = new String("abc");
System.out.println(str1.equals(str2)) ; // true를 반환
/*
String 클래스에는 오버라이딩이 되어있기 때문에
두 hashCode() 반환값이 동일함
*/
System.out.println(str1.hashCode()) ;
System.out.println(str2.hashCode()) ;
// 단, 위 str1, str2 가 String클래스더라도
// Object클래스의 hashCode()와 같이 객체의 주소값으로 해시코드를 생성하는 메서드가 있다.
// System.identityHashCode(Object x)
/*
두 반환값이 다르다.
(오버라이딩하기 이전의 기능이 필요할 때 사용)
*/
System.out.println(System.identityHashCode(str1));
System.out.println(System.identityHashCode(str2));
toString()
메서드" 인스턴스에 대한 정보를 문자열로 제공할 목적으로 정의된 메서드 "
※ 기본적 Object클래스 내 정의된toString()
public String toString() { return getClass().getName()+"@"+Integer.toHexString(hashCode()); // [클래스이름]@[16진수 해시코드 _ 객체주소] }
위에 나온 16진수 해시코드는
hashCode()
를 오버라이딩 하지 않는다면
같은 클래스 객체더라도
각 객체마다 다른 toString()
출력하게 될 것이다.
❓
toString()
오버라이딩물론 16진수 해시코드가 필요하다면 사용할 수 있겠지만
사실 큰 효용성은 없다고 볼 수 있다.
따라서
우리가 알고 싶은 " 멤버들에 대한 정보 "를 출력하게끔 오버라이딩을 할 수 있다.
예를 들면public String toString() { return "(멤버변수 a) : " + (멤버변수 a) + "(멤버변수 b) : "+ (멤버변수 b) ; }
여기서 조심해야 할 것은
전부터 누누히 강조되어왔지만
" 오버라이딩의 조건 " 중
조상클래스의 접근제어자보다 같거나 넓어야 한다는 점 을 명심해야한다.
(위를 보면 Object클래스에 정의된toString()
메서드의 접근제어자는public
이기 때문에
오버라이딩할 때, 동일하게public
으로 해야한다.)