본문 바로가기
생활코딩/JAVA

생활코딩 - JAVA (Object 클래스)

by Love of fate 2020. 12. 31.
728x90
반응형

객체(object)라는 object라는 이름을 가진 클래스를 의미한다.

이 클래스는 특별한 형태의 클래스인데, 이 클래스를 한마디로 정의하자면 시조이다.

모든 클래스의 공통된 조상으로서 Object라는 구체적인 클래스가 있다.

 

1

2

3

package org.opentutorials.javatutorials.progenitor;

 

class O {}

위의 코드는 아래와 코드가 같다.

1

2

3

package org.opentutorials.javatutorials.progenitor;

 

class O extends Object {}

어떤 클래스를 정의했을 때 그 클래스가 다른 클래스를 상속하지 않는다면 자바가 암시적으로 "extend Object"를 추가한다는 뜻이다.

이렇게 하는 이유는 자바는 수많은 클래스가 기본적으로 라이브러리 형태로 제공되고, 클래스를 만들기도 하기때문에 자바에는 엄청나게 많은 클래스가 존재한다. 이러한 클래스를 묶어주는 공통분모로서 Object가 존재하고 동시에 이 Object 클래스가 가진 메소드를 통해 각 클래스가 필소적으로 갖춰야 할 공통적인 기능을 제공하는 것이다.

 

Object 클래스의 API 문서의 위쪽을 보면 Tree라는 메뉴가 있는데 메뉴를 클릭하면 Class Hierarchy라는 클래스의 계층구조가 나타난다.

 

[Object 클래스의 메소드 목록]

위 내용이 중요한 이유는 모든 클래스가 갖고 있는 공통적인 기능을 살펴보는 것이기 때문이다.

그리고 동시에 이를 통해 자바 프로그래밍 언어가 객체지향 언어이고 객체지향이 가진 기능 가운데 상속이 있고 그 상속을 통해 자바라는 언어가 모든 클래스나 객체에 공통적인 기능을 자바답게, 객체지향스럽게 구현하는 사례를 볼 수 있다.

 

[toString] 

Object 클래스가 가진 가장 대표적인 메소드 : toString()

toString()은 객체의 내용을 문자화 한다고 이해하면 된다. 

객체를 문자화하면 어떻게 되는가를 정의하는 것이 toString() 메소드가 하는 역할이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package org.opentutorials.javatutorials.progenitor;
 
class Calculator{
    int left, right;
      
    public void setOprands(int left, int right){
        this.left = left;
        this.right = right;
    }
    public void sum(){
        System.out.println(this.left+this.right);
    }
      
    public void avg(){
        System.out.println((this.left+this.right)/2);
    }
}
  
public class CalculatorDemo {
      
    public static void main(String[] args) {
          
        Calculator c1 = new Calculator();
        c1.setOprands(1020);
        System.out.println(c1);
    }
  
}

1

System.out.println(c1);

필자의 결과는 아래와 같다. @ 뒤의 내용은 각자 다를 것이다.

1

org.opentutorials.javatutorials.progenitor.Calculator@11be650f

이 클래스의 패키지는 org.opentutorials.javatutorials.progenitor이고, 클래스는 Calculatror이며,

이 인스턴스를 식별하는 식별자가 11be650f라는 것이다. ("@"은 아무 의미가 없다.)

즉, 인스턴스의 주소라고 생각하면 되는데 @을 기준으로 앞에있는 부분은 인스턴스가 어떤 클래스에 소속됐는지를 나타내며 뒤에 있는 내용은 해당 인스턴스를 식별하는 값으로 생각하면 된다.

 

toString() 메소드를 명시적으로 호출하지 않고 인스턴스가 담긴 변수만 println() 메소드의 인자로 전달하면 내부적으로 자바가 toString() 메소드를 호출하도록 약속되어 있다. 

 

오버라이드를 통해 toString() 메소드가 출력하는 내용을 바꿀 수 있다. 

 

toString()이 실제로 어떻게 생겼는지 확인하려면 이클립스에서 [Ctrl] 키를 누르고 toString() 메소드 위에 마우스 커서를 갖다 대면 다음과 같은 목록이 나온다. 

[Open Declaration, Open implementation, Open Return Type]

여기서 Open Implementation을 클릭하면 해당 메소드의 구체적은 구현체로 이동할 수있다. 

 

[equals]

equals는 같다라는 뜻이다. 

어떤 두 개의 인스턴스가 서로 같은 인스턴스인지 비교하는 역할을 하는 API가 바로 equals() 메소드 이다.

 

1. 객체 간의 동일성을 비교하고 싶을 때는 == 를 사용하지 말고 equals() 메소드를 이용하자.

2. equals() 메소드를 직접 구현해야 한다면 hashCode() 메소드도 함께 구현해야 함을 알고 이에 대해 분명히 학습한 후

   에 구현하자

3. 이유가 분명하지 않다면 비교 연산자 == 은 원시 데이터 형을 비교할 때만 사용하자. 원시 데이터 형(Primitive Data

   Type) 이란 자바에서 기본적으로 제공하는 데이터 타입으로 byte, short, int, long, float, double, boolean, char 가 있

   다. 이러한 데이터 타입은 new 연산자로 생성하지 않아도 사용할 수 있다는 특징이 있다.

 

* Object에 포함된 여러 API 중에서 toString()을 가급적 구현하는 것을 권자한다. 그래야 프로그램을 이해하기 쉽기 때문

  이다. 

  equals()의 경우 기본적으로 Object 클래스가 가진 equals()를 그대로 사용하는 것을 권장한다.

  그런데 객체를 비교하는 것이 아니라 원시 데이터형과 같은 특수한 데이터 타입을 사용할 때는 비교 연산자를 쓰고     

  String이나 객체를 비교할 떄는 equals()를 쓰면 된다.

[finalize]

finalize()는 객체가 소멸될 때 호출되기로 약속된 메소드 이다. 

인스턴스가 소멸될 떄 어떤 처리해야 할 작업이 있다면 finalize()를 오버라이딩해서 객체가 소멸될 떄 이렁나야 하는 일을 지정할 수있다. 

 

많은 자바 전문가들이 이 메소드의 사용을 여러 가지 이유로 만류하고 있기 떄문에 메소드를 볼 일도 별로 없고, 이 메소드를 직접 사용할 경우 왜 이 메소드를 사용하는가를 분명히 아는 상태에서 사용해야 한다. 

 

사실 finlaize() 대신 가비지컬렉션에 대해 설명하겠다.

가비지 컬렉션(garbage Collecton) '쓰레기를 수집한다' 또는 '버린다'라는 뜻인데 인스턴스를 만드는 것은 내부적으로 컴퓨터의 메모리를 사용하는 것이다. 

RAM을 효율적으로 사용하기 위해 더는 사용하지 않는 데이터를 제거하는 방법을 제공한다.

자바에서도 이러한 방법을 제공하지만 아주 제한적으로 제공하는데, 기 으유는 바로 RAM을 다루는 까다로운 작업을 자바가 자동화 했기 때문이다. 이 작업을 가비지 컬렉션이라 한다. 

 

그 변수를 사용하는 곳이 더는 없다면 이 변수에 담긴 인스턴스는 더는 사용되지 않는다는 것을 의미하기 때문에 자바가 정기적으로 순찰을 돌면서 사용되지 않는 변수를 발견하면 삭제한다. 

어떤 경우에 컴퓨터가 느려지는지 잘 이해하고, 가비지 컬렉션과 가진 지식을 잘 버무려야 좋은 애플리케이션이 만들어진다. 

'java Garbage Collection' 이라는 글을 읽어보면 좋을 것이다. 

 

[clone]

clone은 '복제'란 뜻으로 어떤 객체가 있고 그 객체와 똑같은 것이 필요할 때 그 객체를 복제하는 것이 clone() 메소드가 하는 역할이다.

객체가 복잡해지고 계속해서 상태가변화나는 도중에 똑같은 객체를 만드는 것은 어렵거나 불가능할 수 있다. 이러한 경우네는 바로 clone() 메소드를 사용할 수 있다. 

이 메소드를 이요하면 똑같은 객체를 만들 수 있다. 

 

어떠한 객체를 복제하려면 이 객체가 복제 가능한 객체라는 사실을 자바 가상 머신에 알려줘야 한다. 

Cloneable이라는 인터페이스를 구현하면 된다.

1
2
3
4
5
6
7
8
9
10
11
package org.opentutorials.javatutorials.progenitor;
 
class Student implements Cloneable{
    String name;
    Student(String name){
        this.name = name;
    }
    protected Object clone() throws CloneNotSupportedException{
        return super.clone();
    }
}

Cloneable 인터페이스는 객체가 복제가 가능한 객체라는 사실을 자바 가상 머신에게 알려주기 위한 구분자에 불과하다.

즉, Cloneable은 일종의 약속이다.

 

clone() 메소드의 특성상 적근제어가자 protected이기 떄문에 서로 다른 패키지에서는 호출할 수 없다. 

하지만 클래스가 각기 다른 패키지에 있더라도 상속관계에 있다면 protected 멤버에 접근할 수 있다. 

Exception은 반드시 처리하도록 강제된 예외(검사 예외)이므로 throws CloneNotSupportedException을 추가한다.

 

접근 제어자를 public으로 지정한것은 부모 클래스에 들어있는 clone() 메소드의 접근 제어자는 protected였지만 public이 protected보다 더 개방적이기 떄문이다. 

 

728x90
반응형

'생활코딩 > JAVA' 카테고리의 다른 글

생활코딩 - JAVA (참조)  (0) 2021.01.10
생활코딩 - JAVA (상수와 enum)  (0) 2021.01.10
생활코딩 - JAVA (예외 던지기)  (0) 2020.12.30
생활코딩 - JAVA (예외 (exception))  (0) 2020.12.29
생활코딩 - JAVA (다형성)  (0) 2020.12.29