Chapter 9 java.lang 패키지와 유용한 클래스

Red Culture·2021년 6월 14일

Object 클래스란

-모든 클래스의 최상위 클래스, java.lang.Object 클래스
-모든 클래스는 Object 클래스에서 상속받음
-모든 클래스는 Object 클래스의 메서드를 사용할 수 있음
-모든 클래스는 Object 클래스의 일부 메서드를 재정의하여 사용할 수 있음

  • toString() 메서드
    -객체의 정보를 String으로 바꾸어 사용할 때 유용함
    -자바 클래스 중에는 이미 정의된 클래스가 많음 (String, Integer, Calendar 등..)
    -많은 클래스에서 재정의해서 사용

  • equals() 메서드
    -두 객체의 동일함을 논리적으로 재정의할 수 있음
    (물리적 동일함: 같은 주소를 가지는 객체, 논리적 동일함: 같은 값 (같은 학번의 학생, 같은 주문번호의 주문)
    -> 물리적으로 다른 메모리에 위치한 객체라도 논리적으로 동일함을 구현하기 위해 사용하는 메서드

       Student lee = new Student(100, "이순신");
        Student lee2 = lee;
        Student shin = new Student(100, "이순신");
    
        System.out.println(lee == shin);
        System.out.println(lee.equals(shin));

    -> 위 실행 결과는 lee와 shin 객체의 주소가 다르기 때문에 lee.equals(shin)는 false가 출력된다.
    -> 하지만 다음과 같이 equals() 메서드를 논리적으로 재정의해서 객체의 주소가 아닌 값을 비교할 수 있다.

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Student) {
            Student student = (Student) obj;
            // return (this.studentNumber == student.studentNumber);
            if (this.studentNumber == student.studentNumber) {
                return true;
            } else {
                return false;
            }
        }
        return false;
    }

    -> 위 equals() 메서드를 재정의하고 위 출력문을 실행하면 lee.equals(shin)는 true가 반환된다.
    -> 이렇게 객체가 같다는 의미는 같은 hasCode 값을 갖는다는 의미이다.

  • hashCode() 메서드
    -인스턴스가 저장된 가상머신의 주소를 10진수로 반환
    -두 개의 서로 다른 메모리에 위치한 인스턴스(객체)가 동일하다는 것은?
    1) 논리적으로 동일 (equals()의 반환값이 true)
    2) 동일한 hashCode 값을 가짐 (hashCode()의 반환값이 동일)
    *즉, 원래는 객체마다 hashCode()는 유니크한 값을 갖지만, equals()가 true일 때 자바 내부에서 어떻게 구현해야 동일성을 갖는 의미가 되는가?
    -> hashCode() 메서드를 오버라이딩해서 equals()가 true일 때, hashCode()도 같은 값이 반환될 수 있도록 같다라는 동일성을 나타내기 위한 구현을 한다.

  • clone() 메서드
    -객체의 복사본을 만듬, 기본틀로부터 같은 속성 값을 가진 객체의 복사본을 생성할 수 있음
    -객체지향 프로그램의 정보은닉에 위배되는 가능성이 있으므로 복제할 객체는 cloneable 인터페이스를 명시해야함
    -> 마커 인터페이스(추상 메서드가 없는 인터페이스, Serializable 등..)

Class 클래스

-자바의 모든 클래스와 인터페이스는 컴파일 후 class 파일로 생성됨
-class 파일에는 객체의 정보(멤버변수, 메서드, 생성자 등)가 포함되어 있음
-Class 클래스는 컴파일된 class 파일에서 객체의 정보를 가져올 수 있음
-동적 로딩(런타임)이나 리플렉션, 내 로컬에 자료형이 없는 경우나 모를 때 쓰임
1) String s = new String();
Class c= s.getClass();
2) Class c = String.Class();
3) Class c = Class.forName("java.lang.String"); // 동적 로딩
-> 동적 로딩의 경우 " " 안에 오타가 생길 경우 로딩 되다가 ClassNotFoundException이 발생될 수 있음
-newInstance() 메서드: Class 클래스 메서드로 new 키워드를 사용하지 않고 인스턴스를 생성한다.
*Class 클래스의 forName() 동적 로딩이란?
-컴파일 시에 데이터 타입이 모두 binding 되어 자료형이 로딩되는 것(static loading)이 아니라 실행 중에 데이터 타입을 알고 binding 되는 방식
-실행 시에 로딩되므로 경우에 따라 다른 클래스가 사용될 수 있어 유용함
-컴파일 타임에 체크할 수 없으므로 해당 문자열에 클래스가 없는 경우 예외(ClassNotFoundException)가 발생할 수 있음

String 클래스

String str1 = new String("abc"); // 인스턴스로 생성됨 (힙 메모리)
String str2 = "abc"; // 상수풀에 있는 문자열을 가리킴

    String str1 = new String("abc");
    String str2 = new String("abc");

    System.out.println(str1 == str2);      // false

    String str3 = "abc";
    String str4 = "abc";

    System.out.println(str3 == str4);

-> str1과 str2는 인스턴스로 생성되었기 때문에 다른 메모리의 값을 비교하여 false가 출력되고, str3와 str4는 상수풀에 있는 문자열을 가리키기 때문에 같은 값으로 true를 출력하게 된다.
-String은 immutable하므로 한 번 선언되거나 생성된 문자열을 변경할 수 없다. 따라서 String 메서드의 concat() 메서드 혹은 "+" 를 이용하여 String을 연결하는 경우 문자열을 새로 생성된다. (새로운 메모리가 생성됨, 메모리 낭비가 생길 수 있음)
-StringBuffer와 StringBuilder
-> 가변적인 char[] 배열을 멤버변수라 가지고 있는 클래스, 문자열을 변경하거나 연결하는 경우 사용하면 편리한 클래스
-> StringBuffer는 멀티 쓰레드 프로그래밍에서 동기화가 보장됨, StringBuilder는 보장되지 않음
-> 단일 쓰레드 프로그래밍에서는 StringBuilder를 사용하는 것이 더 좋음
-> toString() 메서드로 String 변환

Wrapper 클래스란

-기본 타입에 해당하는 데이터를 객체로 포장해 주는 클래스이다.
-기본 타입은 기본값이 있어서 null 값을 넣을 수 없기 때문에 기본 타입에 null을 넣고 싶으면 Wrapper 클래스를 활용하면 된다.
-박싱: 기본 타입의 데이터를 래퍼 클래스로 변환하는 과정이다.
-언박싱: 래퍼 클래스에 저장된 값을 기본 타입의 데이터로 변환하는 과정이다.

  • Wrapper 클래스를 사용하는 이유
    1) 컬렉션 클래스를 사용하는 경우에는 객체 형태를 받아야 하기 때문에 Wrapper 형태로 변환하여 넘겨줘야 한다.
    2) 객체 또는 클래스가 제공하는 메서드 사용 (MIN_VALUE, MAX_VALUE 등..)
    3) 숫자, 문자로의 형변환 또는 진법 변환시 사용

-기본 자료형과 Wrapper 클래스와의 연산 시 컴파일러가 박싱/언박싱을 자동으로 진행하면서 형변환이 따로 필요없다. (ex) int + Integer) -> 오토 박싱/언박싱
-new 했을 때와 상수풀에 저장해서 값을 가져오는 것과 메모리 사용하는 것이 다르다.
-래퍼 클래스는 산술 연산을 위해 정의된 클래스가 아니므로, 인스턴스에 저장된 값을 변경할 수 없다. 단지, 값을 참조하기 위해 새로운 인스턴스를 생성하고, 생성된 인스턴스의 값만을 참조할 수 있다.

        int n = 10;
        
        Integer number = new Integer(n);  // 박싱
        int m = number.intValue();        // 언박싱
        
        char c = 'A';
        Character ch = c;              // 오토박싱
        char d = ch;                   // 오토언박싱
profile
자기 개발, 학습 정리를 위한 블로그

0개의 댓글