ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 이것이 자바다 | 11장 기본 API 클래스 (1)
    JAVA/이것이 자바다 2022. 7. 4. 14:39

    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() 메소드를 재정의할 때 확인할 것

    1. 매개값이 기준 객체와 동일한 타입의 객체인지 확인  =>  instanceof 연산자로 확인 - 만약 타입이 다를 경우 false 리턴
    2. 기준 객체 타입으로 강제 타입 변환히여 필드값이 동일한지 검사 (동일 타입의 경우) - 동일하면 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

Designed by Tistory.