이것이 자바다 | 11장 기본 API 클래스 (1)
11.2 java.lang 과 java.util 패키지
1. java.lang 패키지
자바 프로그램의 기본적안 클래스를 담고있는 패키지 -> import 없이 사용 가능
2. java.util 패키지
Arrays, Calendar, Date, Objects, StringTokenizer, Random
11.3 Object 클래스
따로 다른 클래스를 상속하지 않으면 암시적으로 java.lang.Object 클래스를 상속하게 됨
=> 자바의 모든 클래스는 Object 클래스의 자식이거나 자손 클래스임 (Object는 자바의 최상위 부모 클래스)
1. 객체 비교 (equals())
모든 객체가 매개값으로 대입될 수 있음 (Object 타입)
boolean result = obj1.equals(obj2);
객체의 번지를 비교하는 것이 아닌 저장하고 있는 데이터가 동일한가를 판단함
직접 사용되지 않고 하위 클래스에서 재정의하여 논리적으로 동등 비교할 때 사용됨
equals() 메소드를 재정의할 때 확인할 것
- 매개값이 기준 객체와 동일한 타입의 객체인지 확인 => instanceof 연산자로 확인 - 만약 타입이 다를 경우 false 리턴
- 기준 객체 타입으로 강제 타입 변환히여 필드값이 동일한지 검사 (동일 타입의 경우) - 동일하면 true 리턴
2. 객체 해시코드(hashCode())
객체 해시코드란 객체를 식별할 하나의 정수값을 말함
객체의 메모리 번지를 이용하여 해시코드를 만들어 리턴함
HashSet, HashMap, Hashtable가 두 객체가 동등한지 비교하는 방법
•hashCode() 메소드 -> 해시코드 값이 같은지 확인
해시코드 값이 같은면 equals() 메소드로 다시 비교
해시코드 값이 다르면 다른 객체로 판단
=> 객체의 동등 비교를 위해서는 Object의 equals() 메소드와 hashCode() 메소드 모두 재정의하여 논리적 동등일 경우 동일한 해시코드가 리턴되도록 해야 함
@Override
public int hashCode() {
return number;
}
}
3. 객체 문자 정보(toString())
객체를 문자열로 표현한 값 리턴
- Date 클래스는 toString() 메소드를 재정의하여 현재 시스템의 날짜와 시간 정보 리턴
- String 클래스는 toString() 메소드를 재정의하여 저장하고 있는 문자열을 리턴
Date obj = new Date();
System.out.println(obj.toString());
// Wed Nov 13 09:33:06 KST 2013
< toString 재정의 예시 >
public class SmartPhone {
private String company;
private String os;
public SmartPhone(String company, String os) {
this.company = company;
this.os = os;
}
@Override
public String toString() {
return company + ", " + os;
}
}
4. 객체 복제(clone())
원본 객체의 필드값과 동일한 값을 가지는 새로운 객체 생성
원본 객체를 안전하게 보호하기 위함
4-1. 얕은 복제 (thin clone)
단순히 필드값을 복사해서 객체를 복제하는 것
필드가 기본 타입일 경우 값 복사, 필드가 참조 타입일 경우 객체의 번지 복사
clone()으로 객체를 복제하기 위해서는 java.lang.Cloneable 인터페이스를 구현하고 있어야 함
구현하지 않으면 CloneNotSupportedException 예외가 발생하여 복제가 실패됨
=> try-catch 예외처리 필요
try {
Object obj = clone();
} catch(CloneNotSupportedException e) { }
< 활용 예 >
// 복제할 수 있는 클래스 선언
public class Member implements Cloneable{ // 복제할 수 있다는 표시
public String id;
public String name;
public String password;
public int age;
public boolean adult;
public Member(String id, String name, String password, String password, int age, boolean adult) {
this.id = id;
this.name = name;
this.password = password;
this.age = age;
this.adult = adult;
}
// 복제하는 방식의 getMember()
public Member getMember() {
Member cloned = null;
try {
cloned = (Member) clone(); // clone() 메소드의 리턴 타입은 Object이므로 Member 타입으로 캐스팅해야 함
} catch (CloneNotSupportedException e) { }
return cloned;
}
}
4-2. 깊은 복제 (deep clone)
얕은 복제는 복제 객체에서 참조 객체를 변경하면 원본 객체도 변경된 객체를 가지게 됨 (얕은 복제의 단점)
=> 깊은 복제는 참조하고 있는 객체도 복제하는 것을 뜻함
∴ 깊은 복제를 하려면 clone() 메소드를 재정의해서 참조 객체를 복제하는 코드를 직접 작성해야 함
import java.util.Arrays;
// clone() 을 재정의해서 깊은 복제로 변경
public class Member implements Cloneable{ // 복제할 수 있다는 표시
public String name;
public int age;
// 참조 타입 필드 (깊은 복제 대상)
public int[] scores;
public Car car;
public Member(String name, int age, int[] scores, Car car) {
this.name = name;
this.age = age;
this.scores = scores;
this.car = car;
}
@Override
// clone() 메소드 재정의
protected Object clone() throws CloneNotSupportedException {
// 먼저 얕은 복사를 해서 name, age 를 복제
Member cloned = (Member)super.clone(); // Object의 clone() 호출
// scores를 깊은 복제
cloned.scores = Arrays.copyOf(this.scores, this.scores.length); // clone() 메소드 재정의
// car를 깊은 복제
cloned.car = new Car(this.car.model);
// 깊은 복제된 Member 객체를 리턴
return cloned;
}
public Member getMember() {
Member cloned = null;
try {
// 재정의된 clone() 메소드 호출
cloned = (Member) clone(); // clone() 메소드의 리턴 타입은 Object이므로 Member 타입으로 캐스팅해야 함
} catch (CloneNotSupportedException e) {
e.printStackTrace(); //에러 발생의 근원지를 찾아서 단계별로 에러를 출력
}
return cloned;
}
}
5. 객체 소멸자(finalize())
쓰레기 수집기는 객체를 소멸하기 직전에 마지막으로 객체의 소멸자 finalize() 를 실행시킴
finalize() 는 기본적으로 내용이 없음
객체 소멸 전 마지막으로 사용한 자원(데이터 연결, 파일 등)을 닫고 싶거나, 중요한 데이터를 저장하고 싶다면 finalize를 재정의할 수 있음
< finalize 재정의의 예 >
// finalize() 메소드 재정의
public class Counter {
private int no;
public Counter(int no) {
this.no = no;
}
@Override
protected void finalize() throws Throwable {
System.out.println(no + "번 객체의 finalize()가 실행됨");
}
}
11.4 Objects 클래스
Objects 클래스가 가진 정적 메소드
1. 객체 비교(compare(T a, T b, Compare<T>c))
T: 비교할 객체 타입
리턴 타입: int
a가 b보다 작으면 음수, 같으면 0, 크면 양수 리턴
public interface Comparator<T> {
int compare(T a, T b);
}
2. 동등 비교(equals() 와 deepEquals())
a | b | Objects.equals(a, b) |
not null | not null | a.equals(b)의 리턴값 |
null | not null | false |
not null | null | false |
null | null | true |
Objects.deepEquals(Object a, Object b) 는 Arrays.deepEuqals(Object[] a, Object[] b) 와 동일
a와 b가 서로 다른 배열일 경우, 항목 값이 모두 같다면 true 리턴
a | b | Objects.deepEquals(a, b) |
not null (not array) | not null (not array) | a.equals(b)의 리턴값 |
not null (array) | not null (array) | Arrays.deepEquals(a, b)의 리턴값 |
not null | null | false |
null | not null | false |
null | null | true |
3. 해시코드 생성(hash(), hashCode())
Objects.hash(Object... values): 매개값으로 주어진 값들을 이용해서 해시 코드를 생성
- 주어진 매개값들로 배열을 생성하고 Arrays.hashCode(Object[])를 호출해서 해시코드를 얻고 이 값을 리턴
- 클래스가 hashCode() 를 재정의할 때 리턴값을 생성하기 위해 사용하면 좋음
- 클래스가 여러 가지 필드를 가지고 있을 때 이 필드들로부터 해시코드를 생성하게 되면 동일한 필드값을 가지는 동일한 해시코드를 가질 수 있음
@Override
public int hashCode() {
return Objects.hash(field1, field2, field3);
}
Objects.hashCode(Object o) 는 매개값으로 주어진 객체의 해시코드를 리턴 => o.hashCode()와 리턴값 동일
*차이점은 매개값이 null이면 0을 리턴한다는 것
4. 널 여부 조사(isNull(), nonNull(), requireNonNull())
Objects.isNull(Object obj) : 매개값이 null일 경우 true 리턴
Objects.nonNull(Object obj) : 매개값이 not null일 경우 true 리턴
requireNonNull() : 첫 번째 매개값이 not null 이면 첫 번째 매개값 리턴
첫 번째 매개값이 null 이면 모두 NullPointerException을 발생시킴
두 번째 매개값은 NullPointerException의 예외 메시지를 제공 ( .getMessage() )
String str1 = "홍길동";
String str2 = null;
System.out.println(Objects.requireNonNull(str1));
try {
String name = Objects.requireNonNull(str1);
} catch(Exception e) {
System.out.println(e.getMessage());
}
try {
String name = Objects.requireNonNull(str2, "이름이 없습니다.");
} catch(Exception e) {
System.out.println(e.getMessage());
}
5. 객체 문자 정보(toString())
객체의 문자 정보 리턴
리턴 타입 | 메소드(매개 변수) | 설명 |
String | toString(Object o) | not null -> o.toString() null -> "null" |
String | toString(Object o, String nullDefault) | not null -> o.toString() null -> nullDefault |
11.5 System 클래스
1. 프로그램 종료
exit()
- 일반적으로 정상 종료일 경우 0, 비정상 종료일 경우 0 이외의 다른 값을 줌
System.exit(0);
2. 쓰레기 수집기 실행(gc())
JVM이 빠른 시간 내에 쓰레기 수집기를 실행하도록 노력함
System.gc();
3. 현재 시각 읽기(currentTimeMillis(), nanoTime())
프로그램 실행 소요 시간 구하는 데 많이 사용됨
4. 시스템 프로퍼티 읽기(getProperty)
시스템 프로퍼티는 JVM