본문으로 바로가기

[Java] Object 클래스란?

category 프로그래밍/자바 2019. 1. 8. 13:19
java.lang 패키지
  • 자바에서 가장 기본적인 동작을 수행하는 클래스들의 집합
  • java.lang패키지의 클래스는 import문 없이 클래스 이름만으로 사용 가능
  • Interface/Classes/Enum/Exceptions/Errors/Annotation Type

java.lang.Object클래스
  • 자바 클래스의 최고 조상 클래스
  • 자바의 모든 클래스는 Object클래스의 모든 메소드를 바로 사용 가능
  • Object클래스는 필드를 가지지 않으며, 총 11개의 메소드만으로 구성

Object 클래스에는 native라고 선언된것이 있다.
native 란 c,c++ 기능(라이브러리)을 쓰고 싶어서 만들어짐

  1. protected Object clone()
    • 해당 객체의 복제본을 생성, 반환
    • protected Object clone() throws CloneNotSupportedException
    • 사용 목적 : 복사할 인스턴스 값 유지, 새로운 작업에 대해 복사본을 사용함으로써 작업 실패시 기존 값 참조 목적
      • Object클래스의 clone()은 단순히 인스턴스 변수의 값만을 복사, 참조변수의 경우 주소값만 복사함으로 제대로된 복사가 이루어지지 않는다. ->얕은 복사(shallow copy) => 객체의 state만 영향을 받는다. 복사본을 변경할 경우 원본에 영향을 미침
      • 깊은 복사(deep copy)를 위해선 clone()을 오버라이드하여 재정의 필요 
      • 깊은 복사는 굉장히 어려운것이다. 
      • 만약 하나의 객체가 tree 형태로 되어있다면 tree내의 모든 하위 객체들 또한 cloneable()을 구현해서 deep copy 해야한다. 
      • 깊은 복사는 원본을 유지하고 새롭게 만들어 내는것이라 볼수 있는데 원본을 유지하고 싶을때는 언제일까?
    • 사용 방법
      • Cloneable 인터페이스 구현
      • 예외 처리(CloneNotSupportedException) -> checked Exception이므로 반드시 예외처리 실행
      • protected -> public

  2. public boolean equals(Object obj)
    • public boolean equals(Object obj){   return (this==obj)    }
      • reflexive(재귀의, 되돌아오는) : 자기 자신과의 비교에서 항상 true를 return한다. x.equals(x) == true
      • symmetric(대칭적인) : x.equals(y) = y.equals(x) =true (교환 법칙)
      • transitive(전이하는) : x.equals(y) = y.equals(z) 이면  x.equals(z)
      • consistent(일관된) : 반복된 비교에도 일관된 결과를 반환
    • Null이 아닌 해당객체와 전달받은 객체의 참조 변수(non-null reference value)가 같은지 여부를 반환
    • 즉, 두개의 참조변수가 같은 객체를 참조하고 있는지, 참조변수에 저장된 주소값이 같은지를 판단
    • 같은 class타입의 참조변수에 저장된 객체라도 생성시 다른 공간에 저장되기때문에 주소값은 다를 수밖에 없다. -> 같은 타입의 객체에 대해 주소값이 아닌 인스턴스 변수(내용)를 비교하고 싶은경우 오버라이드해서 재정의 후 사용
    • String클래스는 Object의 equals메소드를 오버라이드하여 문자열 비교에 사용
    • equals메소드 오버라이드시 hashCode메소드도 같이 오버라이드 해야함
    • equals는 왜 중요하지?
    • => equals는 같은 객체인지 판변하기 위한 메소드이며 
    • => object equals는 기본적으로 인스턴스의 주소를 비교한다.
    • => 하지만 equals가 중요한 이유는 논리적인 동등을 표현하기 위해 사용한다.
    • => 예를들어 string a = "aa";  string b = new string("aa");
    • => a.equals(b);를 하게되면 true 값이 나오게 된다.
    • => equals 메소드를 override 하지않고 object equals의 기본을 사용하게 되면 값은 false가 나오게 된다.
    • => 다른 인스턴스 주소를 가지고 있으니까!! 하지만 equals를 재정의 하면서 논리적인 비교를 만들게 된다.
    • => String 클래스의 경우 값을 비교하게 된다. 

  3. protected void finalize()
    • 객체가 더이상 참조되지 않아 소멸될때 가비지 컬랙터에 의해 자동적으로 호출
    • finalizer는 예측이 불가능하고, 위험하며 대부분 불필요하다 (deprecated - 중요도가 떨어져 더이상 사용되지 않고 사라지게 될것)
      • 언제 실행될지 알수 없다. -> 어떤 객체가 더이상 필요 없어진 시점에 그 즉시 finalize가 실행되지 않을 수도 있다. 
      • 인스턴스 반납을 지연시킬 수 있다 -> finalizer 스레드는 우선순위가 낮아서 언제 실행될지 알수 없다. 따라서 우선순위가 높은 다른 작업에 의해 처리가 미뤄질 경우, OutOfMemoryException이 발생할 수 있다. 
      • 반드시 실행된다는 보장이 없다. -> System.gc
      • 예외가 발생하면 무시된다. -> finalize()실행 동안에 catch되지 않은 예외가 발생하면, 실행이 중단되고 stack trace가 실행되지않고, 예외가 무시되어 예측할 수 없는 결과를 발생시킬 수 있다.
      • 성능이 저하된다. -> AutoCloseable 인터페이스를 구현한 객체를 만들고 'try-with-resource'로 자원반납하는데 12ns소요, Finalizer를 사용한 경우 550ns소요, 50배 차이
    • finalizer를 유용하게 쓸수있는 딱 두가지 경우
      • 안전망 역할로 자원을 반납하고자 하는 경우 -> 객체의 종료 메서드 호출에 실패할 경우를 대비해서 사용
      • 네이티브 리소스를 정리해야 하는 경우 -> native란 자바 외의 C, C++와 같은 프로그래밍 언어를 의미, Native API를 이용한 코드와 연관된 Native peer 객체는 gc에 의해 처리되지 않을 수도 있음으로 사용
      • finalize() 메소드는 사용과 재정의(override)하지마라!!

  4. public Class<? extends |X|> getClass()
    • 해당 인스턴스의 클래스 타입을 반환
    • return 타입이 Class 객체 : 이름이  Class인 클래스의 객체(java.lang.Class)
      • public final class Class implements ...{   }
      • ClassLoader(JVM)에 의해 메모리에 올라갈때 자동으로 생성
    • Returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class.
    • instanceof연산자로도 클래스 타입을 알 수 있지만, 이 경우 부모 클래스도 같은 타입으로 취급한다. 때문에 더 정확한 처리를 위해선 getClass를 사용한다.

  5. public int hashCode()
    • 해시 함수(hash function)를 이용해 해당 객체의 해시코드값을 반환함
    • 어플리케이션 실행 동안 반복된 객체 호출에 대해 일관된 해시코드값을 반환한다.
    • 두 객체의 equals()결과가 true일 경우, 해시코드값은 같다. -> Object클래스에서는 객체의 주소값을 이용해 해시 코드를 생성(일반적으로 해시코드가 같은 두 객체가 존재하는것이 가능)
    • 기본적으로 hashCode()는 각 객체마다 고유한 값을 가지게 된다. 하지만 재정의를 통해 같은 값을 가질수 있다.
    • 그런데 왜 return 형은 int 일까?
    • => This method is supported for the benefit of hash tables such as those provided by HashMap. (java api)
    • => hashCode()는 hash tables와 같은 이점을 지원하는 메소드이다. (hash table에 대한 개념은 다시 포스팅하겠다.)
    • => 특정 key들을 특정 공간에 넣어주기 위한 인덱스가 필요하기 때문에 인덱스값을 위해 int 형을 쓴다고 생각하면 된다(hash table 개념을 알면 쉽다)
    • => hash table에서 데이터를 검색하게 될 경우 O(k)~ O(n) 이 걸리는데 왜 O(n) 이 걸릴까?
    • => hashCode()를 재정의 하지 않는다면 인스턴스마다 값이 고유하지만
    • => 재정의 할경우 hashCode()가 같을수 있다.
    • => 만약 같게 되면 특정 공간에 여러개를 넣게 된다. 그렇게 계속하다보면 O(n)이 나온다.
  6. public String toString()
    • 해당객체를 "텍스트적으로 나타낼 수 있는" 문자열을 반환
    • public String toString(){ return getClass().getName()+"@"+Integer.toHexString( hashCode() ) }
    • 클래스명@해시코드를 16진수로 표기
    • String클래스의 toString의 경우, 해당 메소드를 오버라이드하여 String인스턴스가 가지고 있는 문자열을 반환하도록 재정의하여 사용한다.
    • 내가 원하는것을 문자열로 보여주고 싶을때 사용하는것이다.
    • 데이터를 가진 객체는 toString()을 재정의 해주는게 좋다.

  7. public void notify()
    • 해당 객체의 대기( wait)하고 있는 하나의 스레드를 다시 실행할 때 호출함
  8. public void notifyAll()
    • 해당 객체의 대기하고 있는 모든 스레드를 다시 실행할 때 호출함
  9. public void wait()
    • 해당 객체의 다른 스레드가 notify()나 notifyAll()메소드를 실행 할 때까지 현재 스레드를 일시적으로 대기(wait)시킬때 호출
  10. public void wait(long timeout)
    • 해당 객체의 다른 스레드가 notify()나 notifyAll()메소드를 실행 하거나, 전달받은 시간이 지날때까지 현재 스레드를 일시적으로 대기(wait)시킬때 호출
  11. public void wait(long timeout, int nanos)
    • 해당 객체의 다른 스레드가 notify()나 notifyAll()메소드를 실행 하거나, 전달받은 시간이 지나거나, 다른 스레드가 현재 스레드를 인터럽트(interrupt)할 때까지 현재 스레드를 일시적으로 대기(wait)시킬때 호출


'프로그래밍 > 자바' 카테고리의 다른 글

Network란 무엇인가?  (0) 2019.01.18
[Java] 해싱(Hashing)이란?  (0) 2019.01.08
[Java] final 이란?  (0) 2019.01.08
Exception 처리방법  (0) 2019.01.06
[JAVA] 자바 class 파일 실행방법  (1) 2018.12.31