[Java] 기본 API 클래스 ①

kiteB·2022년 1월 30일
0

Java

목록 보기
28/35
post-thumbnail

[ 자바 API 도큐먼트 ]

지금부터는 자바에서 제공하는 API(Application Programming Interface)에 대해서 알아보자.

API는 라이브러리라고 부르기도 하는데, 프로그램 개발에 자주 사용되는 클래스 및 인터페이스 모음을 말한다.

우리가 사용해왔던 String 클래스와 System 클래스도 모두 API에 속하는 클래스들이다.

API 도큐먼트는 이러한 API를 쉽게 찾아 이용할 수 있도록 문서화한 것을 말한다.

🔗 API 도큐먼트 사이트


[ java.langjava.util 패키지 ]

자바 애플리케이션을 개발할 때 공통적으로 많이 사용하는 패키지는 java.lang, java.util, java.time 패키지일 것이다. 하나씩 살펴보자!

1. java.lang 패키지

자바 프로그램의 기본적인 클래스를 담고 있는 패키지이다. 그러므로 java.lang 패키지에 있는 클래스와 인터페이스는 import 없이 사용할 수 있다.

java.lang 패키지에 속하는 주요 클래스는 다음과 같다.


2. java.util 패키지

컬렉션 클래스들이 대부분을 차지하고 있다.


[ Object ]

클래스를 선언할 때 extends 키워드로 다른 클래스를 상속하지 않으면 암시적으로 java.lang.Object 클래스를 상속하게 된다. 따라서 자바의 모든 클래스는 Object 클래스의 자식이거나 자손 클래스이다. Object는 자바의 최상위 부모 클래스에 해당한다.

Object 클래스는 필드가 없고, 메소드로 구성되어 있다. 이 메소드들은 모든 클래스가 Object를 상속하기 때문에 모든 클래스에서 사용이 가능하다.


1. 객체 비교 ( equals() )

다음은 Objectequals() 메소드이다.

public boolean equals(Object obj) { ... }

equals() 메소드의 매개 타입이 Object이므로 모든 객체가 매개값으로 대입될 수 있다. (모든 객체가 Object 타입으로 자동 타입 변환될 수 있기 때문이다.)

Object 클래스의 equals() 메소드는 비교 연산자인 ==과 동일한 결과를 리턴한다. 두 객체가 동일한 객체라면 true를 리턴하고, 그렇지 않으면 false를 리턴한다.

Object obj1 = new Object();
Object obj2 = new Object();

boolean result = obj1.equals(obj2);	//obj1은 기준 객체, obj2는 비교 객체
boolean result = (obj1 == objs)

자바에서는 두 객체를 동등 비교할 때 equals() 메소드를 흔히 사용한다. equals() 메소드는 두 객체를 비교해서 논리적으로 동등하면 true를 리턴하고, 그렇지 않으면 false를 리턴한다. 논리적으로 동등하다는 것은 같은 객체이건 다른 객체이건 상관없이 객체가 저장하고 있는 데이터가 동일함을 뜻한다.

예를 들어 String 객체의 equals() 메소드는 String 객체의 번지를 비교하는 것이 아니고, 문자열이 동일한지 조사해서 같다면 true를 리턴하고, 그렇지 않다면 false를 리턴한다. 이것이 가능한 이유는 String 클래스가 Objectequals() 메소드를 재정의(오버라이딩)해서 번지 비교가 아닌 문자열 비교로 변경했기 때문이다.

Objectequals() 메소드는 직접 사용되지 않고 하위 클래스에서 재정의하여 논리적으로 동등 비교할 때 이용된다. 예를 들어 Member 객체는 다르지만 id 필드값이 같으면 논리적으로 동등한 객체로 취급하고 싶을 경우 Objectequals() 메소드를 재정의해서 id 필드값이 같음을 비교하면 된다.

equals() 메소드를 재정의할 때에는 매개값(비교 객체)이 기준 객체와 동일한 타입의 객체인지 먼저 확인해야 한다.
Object 타입의 매개 변수는 모든 객체가 매개값으로 제공될 수 있기 때문에 instanceof 연산자로 기준 객체와 동일한 타입인지 제일 먼저 확인해야 한다. 만약 비교 객체가 다른 타입이라면 equals() 메소드는 false를 리턴해야 한다.

비교 객체가 동일한 타입이라면 기준 객체 타입으로 강제 타입 변환해서 필드값이 동일한지 검사하면 된다. 필드값이 모두 동일하다면 true를 리턴하고 그렇지 않으면 false를 리턴하도록 작성한다.

예제

  • Member
public class Member {
    public String id;

    public Member(String id) {
        this.id = id;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Member) {
            Member member = (Member) obj;
            if (id.equals(member.id)) {
                return true;
            }
        }
        return false;
    }
}
  • MemberExample
public class MemberExample {
    public static void main(String[] args) {
        Member obj1 = new Member("blue");
        Member obj2 = new Member("blue");
        Member obj3 = new Member("red");

        //obj1과 obj2 비교
        if (obj1.equals(obj2)) {
            System.out.println("obj1과 obj2는 동등하다.");
        } else {
            System.out.println("obj1과 obj2는 동등하지 않다.");
        }

        //obj1과 obj3 비교
        if (obj1.equals(obj3)) {
            System.out.println("obj1과 obj3은 동등하다.");
        } else {
            System.out.println("obj1과 obj3은 동등하지 않다.");
        }
    }
}
  • 실행 결과
obj1과 obj2는 동등하다.
obj1과 obj3은 동등하지 않다.

2. 객체 해시코드( hashCode() )

객체를 식별할 하나의 정수값을 말한다.

ObjecthashCode() 메소드는 객체의 메모리 번지를 이용해서 해시코드를 만들어 리턴하기 때문에 객체마다 다른 값을 가지고 있다.

논리적 동등 비교 시 hashCode()를 오버라이딩할 필요성이 있는데, HashSet, HashMap, Hashtable은 다음과 같은 방법으로 두 객체가 동등한지 비교한다.

우선 hashCode() 메소드를 실행해서 리턴된 해시코드 값이 같은지를 본다.

  • 해시코드 값이 다르면 다른 객체로 판단한다.
  • 해시코드 값이 같으면 equals() 메소드로 다시 비교한다.

그렇기 때문에 hashCode() 메소드가 true가 나와도 equals()의 리턴값이 다르면 다른 객체가 된다.

예제

  • Key
public class Key {
    public int number;

    public Key(int number) {
        this.number = number;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Key) {
            Key compareKey = (Key) obj;
            if (this.number == compareKey.number) {
                return true;
            }
        }
        return false;
    }
}
  • KeyExample
public class KeyExample {
    public static void main(String[] args) {
        //Key 객체를 식별키로 사용해서 String 값을 저장하는 HashMap 객체 생성
        HashMap<Key, String> hashMap = new HashMap<Key, String>();

        //식별키 "new Key(1)"로 "홍길동"을 저장함
        hashMap.put(new Key(1), "홍길동");
        
        //식별키 "new Key(1)"로 "홍길동"을 읽어옴
        String value = hashMap.get(new Key(1));
        System.out.println(value);
    }
}
  • 실행 결과
null

HashMap의 식별키로 Key 객체를 사용하면 저장된 값을 찾아오지 못한다. number 필드값이 같더라도 hashCode() 메소드에서 리턴하는 해시코드가 다르기 때문에 다른 식별키로 인식하기 때문이다.

의도한 대로 "홍길동"을 읽을려면 다음과 같이 재정의한 hashCode() 메소드를 Key 클래스에 추가하면 된다. hashCode()의 리턴값을 number 필드값으로 했기 때문에 저장할 때의 "new Key(1)"과 읽을 때의 "new Key(1)"은 같은 해시코드가 리턴된다.

  • Key - hashCode() 메소드 재정의 추가
public class Key {
    ...
    @Override
    public int hashCode() {
        return number;
    }
}

저장할 때의 new Key(1)과 읽을 때의 new Key(1)은 사실 서로 다른 객체이지만 HashMaphashCode()의 리턴값이 같고 equals() 리턴값이 true로 나오기 때문에 동등 객체로 평가한다. 즉, 같은 식별키로 인식한다!

결론적으로 말해서 객체의 동등 비교를 위해서는 Objectequals() 메소드만 재정의하지 말고 hashCode() 메소드도 재정의해서 논리적 동등 객체일 경우 동일한 해시코드가 리턴되도록 해야 한다.


[ 참고자료 ]

이것이 자바다 책

profile
🚧 https://coji.tistory.com/ 🏠

0개의 댓글