Java

Object 클래스

모든 클래스의 조상인 Object 클래스에 대해서 알아본다.

상속

자바에서 상속이란 필수적이다. 여러분이 상속하건 하지 않았건 기본적인 상속을 하게 된다.

package org.opentutorials.javatutorials.progenitor;

class O {}

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

package org.opentutorials.javatutorials.progenitor;

class O extends Object {}

자바에서 모든 클래스는 사실 Object를 암시적으로 상속받고 있는 것이다. 그런 점에서 Object는 모든 클래스의 조상이라고 할 수 있다. 그 이유는 모든 클래스가 공통으로 포함하고 있어야 하는 기능을 제공하기 위해서다.

API 문서를 보자.

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

메소드의 목록을 살펴보자.

위의 그림은 Object 클래스가 가지고 있는 메소드를 보여준다. 다시 말해서 자바의 객체는 위의 메소드들을 반드시 가지고 있다고 할 수 있다. 이 중에 중요하면서 입문 단계에서 이해할 수 있는 API들을 살펴보자.

toString

toString은 객체를 문자로 표현하는 메소드이다. 기본 예제인 계산기 코드를 보자.

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(10, 20);
        System.out.println(c1);
    }
 
}

25라인에 아래 코드는 클래스 Calculator의 인스턴스 c1을 화면에 출력하고 있다.

System.out.println(c1);

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

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

이것은 인스턴스 c1이 클래스 Calculator의 인스턴스라는 의미다. @ 뒤의 내용은 인스턴스에 대한 고유한 식별 값이라고 생각하자.

위의 정보도 유용한 정보이지만 클래스 설계자의 필요에 따라서 toString의 결과를 더욱 유용하게 만들 수 있다. 예를들어 계산기 인스턴스의 left, right 값을 알 수 있다면 개발을 좀 더 편하게 할 수 있을 것이다.

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 String toString(){
        return "left : " + this.left + ", right : "+ this.right;
    }
}
 
public class CalculatorDemo {
     
    public static void main(String[] args) {
         
        Calculator c1 = new Calculator();
        c1.setOprands(10, 20);
        System.out.println(c1);
        System.out.println(c1.toString());
    }
 
}

차이점

실행결과

left : 10, right : 20
left : 10, right : 20

클래스 Calculator에 toString을 재정의(overiding)했다. 그리고 인스턴스를 System.out.println의 인자로 전달하니까 toString을 명시적으로 호출하지 않았음에도 동일한 효과가 나고 있다. toString 메소드는 자바에서 특별히 취급하는 메소드다. toString을 직접 호출하지 않아도 어떤 객체를 System.out.print로 호출하면 자동으로 toString이 호출되도록 약속되어 있다.

이를 통해서 인스턴스 c1의 상태를 쉽게 파악할 수 있게 되었다.

equals

equals는 객체와 객체가 같은 것인지를 비교하는 API이다. 객체 간에 같고 다름은 필요에 따라서 달라질 수 있기 때문이다.

package org.opentutorials.javatutorials.progenitor;

class Student{
    String name;
	Student(String name){
		this.name = name;
	}
	public boolean equals(Object obj) {
		Student _obj = (Student)obj;
		return name == _obj.name;
	}
}

class ObjectDemo {

	public static void main(String[] args) {
		Student s1 = new Student("egoing");
		Student s2 = new Student("egoing");
		System.out.println(s1 == s2);
		System.out.println(s1.equals(s2));

	}

}

결과는 아래와 같다.

false
true

아래 코드를 보자.

System.out.println(s1 == s2);

결과는 false다.

그 이유는 s1과 s2가 서로 다른 객체이기 때문이다. 어찌 보면 당연한 결과다. 하지만 두 개의 객체가 논리적으로는 egoing이라는 값을 가지고 있기 때문에 객체를 만든 필자는 저 두 개의 객체가 같은 객체로 간주 되었으면 좋겠다. 이럴 때 클래스 Object의 메소드 equals를 overiding하면 된다. 

public boolean equals(Object obj) {
	Student _obj = (Student)obj;
	return name == _obj.name;
}

위의 코드 (Student)obj 는 메소드 equals로 전달된 obj의 데이터 타입이 Object이기 때문에 이를 Student 타입으로 형 변환하는 코드다.  아래 코드를 통해서 현재 객체의 변수 name과 equals의 인자로 전달된 객체의 변수 name을 비교한 결과를 Boolean 값으로 리턴하고 있다. 이 값에 따라서 두 개의 객체는 같거나 다른 것이 된다. 

return name == _obj.name;

그런데 eqauls를 제대로 사용하기 위해서는 hashCode라는 클래스도 함께 구현해야 한다. 하지만 이에 대한 이야기는 우리 수업의 범위를 넘어서고 그 효용(사용 빈도)도 높지 않기 때문에 더 이상 설명을 하지 않겠다. 하지만 이 메소드의 취지를 이해하는 것은 또한 중요하기 때문에 언급을 하지 않을 수는 없었다. 메소드 equals에 대해서 필자가 권고하는 입장은 아래와 같다.

1. 객체 간에 동일성을 비교하고 싶을 때는 ==를 사용하지 말고 equals를 이용하자.

2. equals를 직접 구현해야 한다면 hashCode도 함께 구현해야 함을 알고 이에 대한 분명한 학습을 한 후에 구현하자.

3. equals를 직접 구현해야 한다면 eclipse와 같은 개발도구들은 equals와 hashCode를 자동으로 생성해주는 기능을 가지고 있다. 이 기능을 이용하는 것을 고려해보자. 아래 그림을 참고하자.

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

원시 데이터 형(Primitive Data Type)이란 자바에서 기본적으로 제공하는 데이터 타입으로 byte, short, int, long, float, double, boolean, char가 있다. 이러한 데이터 타입들은 new 연산자를 이용해서 생성하지 않아도 사용될 수 있다는 특징이 있다.

 finalize

finalize는 객체가 소멸될 때 호출되기로 약속된 메소드이다. 여기서는 이 메소드의 취지만 이해하면 된다. 많은 자바의 전문가들이 이 메소드의 사용을 만류하고 있다.

이 메소드 보다는 가비지 컬렉션(garbage collection)에 대해서 알아보자. 인스턴스를 만드는 것은 내부적으로는 컴퓨터의 메모리를 사용하는 것이다. 여기서 말하는 메모리는 RAM을 의미한다. 램은 가장 빠른 저장 장치이기 때문에 컴퓨터 프로그램들은 이 램에 저장된 후에 동작하게 된다. 하지만 램은 가격이 비싸고 용량이 적기 때문에 램은 컴퓨터에서 가장 소중한 저장 장치라고 할 수 있다. 그러므로 램의 적게 사용하는 프로그램이 좋은 프로그램이다. 그런 이유로 많은 프로그래밍 언어들이 램을 효율적으로 사용하기 위해서 더 이상 사용하지 않는 데이터를 램에서 제거할 수 있는 방법들을 제공한다.

하지만 자바에서는 이러한 방법이 제한적으로 제공되고 있는데 그것은 자동으로 해주기 때문이다. 이 작업을 자동화한 것을 가비지 컬렉션이라고 한다. 이를테면 어떤 인스턴스를 만들었고, 그것을 변수에 담았다. 그런데 그 변수를 사용하는 곳이 더 이상 없다면 이 변수와 변수에 담겨있는 인스턴스는 더 이상 메모리에 머물고 있을 필요가 없는 것이다. 자바는 이를 감지하고 자동으로 쓰지 않은 데이터를 삭제한다. 따라서 개발자가 사용하지 않는 데이터를 직접 삭제하는 작업을 하지 않아도 되는 것이다. 이것은 어려운 메모리 관리로부터 개발자들의 부담을 경감시킨 도약이라고 할 수 있다.

그럼에도 불구하고 좋은 에플리케이션을 만들기 위해서는 가비지 컬렉션에 대한 이해는 필요하다. 하지만 이는 우리 수업의 취지를 벗어나기 때문에 링크로 대체하겠다.

Java Garbage collection(NHN Hello world 블로그)

clone

clone은 복제라는 뜻이다. 어떤 객체가 있을 때 그 객체와 똑같은 객체를 복제해주는 기능이 clone 메소드의 역할이다. 예를 보자.

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();
	}
}

class ObjectDemo {

	public static void main(String[] args) {
		Student s1 = new Student("egoing");
		try {
			Student s2 = (Student)s1.clone();
			System.out.println(s1.name);
			System.out.println(s2.name);
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}

}

차이점

Student 예를 조금 변형했다. 결과는 아래와 같다. 복사에 성공했다.

egoing
egoing

위의 코드에서 클래스 Student가 인터페이스 Cloneable을 구현하고 있는 것을 주의 깊게 살펴보자. 인터페이스 Cloneable의 코드는 실제 내용은 아래와 같다.

public interface Cloneable {}

비어있는 인터페이스다. 그럼에도 불구하고 이것을 사용한 이유는 클래스 Student가 복제 가능하다는 것을 표시하기 위한 것이다. 만약 이 인터페이스를 구현하지 않고 있는 클래스에 대한 복제를 시도하면 오류가 발생할 것이다.

만약 복사를 보다 정교하게 하고 싶다면 오버라이딩 한 메소드 clone를 직접 구현하면 된다. 하지만 이에 대한 논의는 우리 수업의 범위를 애매하게 넘어서는 것이기 때문에 필자는 설명하지 않는 것을 택하겠다.

이해해야 하는 것과 알아야 하는 것

Object 클래스를 놓고 생각해보자. 이 클래스가 모든 클래스의 부모라는 사실은 이해의 영역이 아니라 약속의 영역이다. 즉 자바를 만든 측과 자바를 사용하는 측의 약속이다. 그리고 이 클래스가 clone이나 toString과 같은 메소드를 가지고 있다는 것 또한 이해의 영역이 아니라 숙지해야 하는 영역이다. 한편 모든 클래스가 toString을 사용할 수 있고 또한 이 메소드를 새롭게 재정의 할 수 있다는 점은 이해의 영역이다. 어떤 지식을 배울 때는 이해해야 하는 것과 그냥 알아야 하는 것을 잘 분별하는 것이 중요하다.

댓글

댓글 본문
작성자
비밀번호
  1. SK Kim
    음..저도 protected method에 대한 의문이 님과 비슷하지만 의문이 아직 해결 되지 않았네요.
    다음과 같이 테스트 해보면 원래 이해한 내용이 일치하는데 Object클래스는 뭔가 더 있는듯.

    [Test1.java]

    package ...test1
    import ...test2.*;

    public class Test1 extends Test2{

    public static void main(String[] args) {
    Test2 t1 = new Test2();
    //t1.meth(); //error, visibility
    Test1 t2 = new Test1();
    t2.meth(); //normal
    }
    }

    [Test2,java]

    package ...test2;

    public class Test2 {

    protected void meth() {
    System.out.println("protected");
    }
    }
    대화보기
    • JustStudy
      고맙습니다
    • JSPARK
      어떤 지식을 배울 때는 이해해야 하는 것과 그냥 알아야 하는 것을 잘 분별하는 것이 중요하다. 주옥같은 말이네요. 어떤 언어를 배우던 늘 이해하는 것이 아니라 그냥 알아야 하는 부분은 꼭 있는것 같아요.
    • 김트라슈
      감사합니다~~
    • freebeing1
      앗 지금보니 오타였네요 Clonable -> Cloneable 입니다.
      대화보기
      • 찐똥구리구리
        우왓, 감사합니다. Clonable이라는 인터페이스가 있었군요. 덕분에 클리어 해졌습니다. 감사합니다 :)
        대화보기
        • freebeing1
          앗 오히려 제가 잘못 생각했던 것 같습니다. protected 메소드는 서로 다른 패키지에서 상속하는 것으로 사용가능하다는 말씀이 맞는 것 같아요. 그래서 왜 오버라이딩을 해야하는지 저도 잘 모르겠어서, 저도 궁금해져서 찾아보다가 Clonable 이라는 인터페이스의 자바문서에 주석으로 이런 내용이 있는 걸 봤습니다.

          * By convention, classes that implement this interface should override
          * <tt>Object.clone</tt> (which is protected) with a public method.
          * See {@link java.lang.Object#clone()} for details on overriding this
          * method.

          해석을 해보면,

          관례상, 이 인터페이스를 구현하는 클래스는 (protected 메소드인) Object.clone 메소드를 반드시 오버라이드해야 합니다. 이 메소드를 오버라이드하는 것에 관한 상세한 내용은 java.lang.Object#clone()을 보십시오.

          라는 내용입니다.
          좋은 지적 감사해요^^ 덕분에 한가지 배웠습니다 :)
          대화보기
          • 찐똥구리구리
            아, 어렵네요. 데이터타입protected는 서로다른패키지에서 상속하는 것으로 사용가능하고, 모든 클래스는 기본적으로 Object클라스를 상속하니까. clone()은 protected이고, 오버라이딩 여부와 관계없이 사용가능할 거 같았는데. 뭔가 제가 놓치고 있는것이...

            혹시 알고 계시다면 답변 좀 부탁드릴께요 :)
            대화보기
            • freebeing1
              Object 클래스에 선언되어있는 clone이라는 메소드의 타입이 protected이기 때문에 오버라이딩을 해줘야 사용할 수 있는 것 같습니다
              대화보기
              • 오빠는다르다
                감사합니다.
              • 생코는혁명이여
                clone 강의에서

                clone 메소드를 오버라이딩 한 걸 지워봤더니
                s1.clone()에 not visible이라는 에러가 뜨는데요

                clone메소드를 사용하고 싶으면 반드시 오버라이딩 해줘야 해요?
              • Amertrin
                물론 말씀하신대로 하셔도 실행에는 문제가 없을거에요~

                http://docs.oracle.com......tml
                하지만 위의 링크를 참고해보시면 이해가 쉬우실 거에요.

                .equals의 상위 클래스인 java.lang.Object에서 .equals를 찾아보시면 인자를 Object 데이터 타입으로 받고있죠?

                equals를 오버라이딩해서 재정의하는 목적이기 떄문에 이고잉님 코드에서는 Object 데이터 타입으로 인자를 받으신 거에요~

                만약 질문자님처럼 Student 데이터 타입으로 인자를 받는다면 equals 메소드를 오버라이딩 하는 것이 아닌 오버로딩 하는것이겠죠?
                만약 Student 메소드 이외에 여러개의 객체 데이터 타입을 인자로 받는다고 가정한다면 Studen 데이터 타입만을 인자로 받을 수는 없겠죠~? (이 말이 이해안가신다 하시더라도 후에 .equals를 사용하시다보면 자연스레 이해되실거에요ㅎㅎ)
                대화보기
                • wiseman Lee
                  저도 왜 clone 메쏘드가 protected 일까 해서
                  stackflow 에 들어가 검색해 봤습니다!

                  http://stackoverflow.com......ect

                  참조하시면 될 것 같습니다.
                  대화보기
                  • magictical
                    생성자는 클래스의 유형을 만들때 사용됩니다.
                    equals는 Object클래스의 메소드이므로 생성자를 사용할수 없죠. 약간 착각하신것 같네요.

                    생성자는 마치 메소드처럼 동작하는데 이를 이용해서 오버로딩하면 다양한 유형의 생성자를 만들수있죠.
                    Duck 클래스가있다면
                    ex) Duck(), Duck(String name), Duck(String name, int i) ...등등
                    대화보기
                    • cocohodu
                      좋은강의 감사합니다
                    • 데이나
                      좋은글입니다. 배우고 갑니다~
                    • 감사합니다! 컴공과이지만 프로그래밍을 어려워하던 제가 하나씩 해나가고 있어요!
                      앞으로도 좋은 강의 부탁드려요ㅎㅎㅎ
                    • 풍운도장
                      잘 배웠습니다.~~
                    • 사각하늘
                      오브젝트 클래스의 자바파일을 살펴보다가 생긴 의문인데요. 파일을 열어보면 초반에
                      private transient Class<?> shadow$_klass_;
                      라고 되어있는데, 왜 저기에 transient를 사용했는지 궁금하네요. 제가 알기론 transient 키워드는 시리얼화에서 제외항목을 만들고 싶은 구문에 적용한다고 알고 있습니다. 그렇다면 오브젝트 클래스가 모든 클래스의 부모인 상황에서 멤버변수에 transient 키워드를 사용할 경우 단순히 생각해 봤을 때 어떤 클래스를 만들고 시리얼화를 적용하면 이 부분은 제외가 될거고 이는 문제가 될 수도 있을 듯한데, 여기에 transient가 적용된 이유가 뭔지 궁금합니다.
                    • 육점이
                      항상 좋은 강의 감사합니다!!!!!

                      예외를 어떤식으로 던지고 어떤식으로 그 예외를 처리하는지는 이해가 되는데,
                      결국 예외를 던지는 이유를 잘 모르겠어요ㅠㅠㅠ 왜그런걸까요?
                    • dklee
                      안녕하세요. 8:27초 정도에서 설명하실때 Protected 인
                      protected Object clone() throws CloneNotSupportedException{
                      return super.clone();
                      }

                      이부분을 Public으로 바꾸실때 더 개방적인 경우는 바꾸는게 가능하다고 하셨는데 이부분이 가능한건지 이해가 잘 안갑니다. 알려주시면 감사하겠습니다.
                      강의 잘 듣고 있습니다.
                    • 박사급인제
                      equals 이부분에서 기본생성자를 정의 해야하는거 아닌가요??
                      기본생성자()매개변수가를 담고잇는 생성자를 생성하는데 그러면 기본생성자는 생성되지 않으니깐
                      기본 생성자 정의한후 매개변수가 있는 생성자를 정의해야하는거 아닌가??
                      수업 잘못들었나벼 ㅠㅠ
                    • 카레이나
                      오브젝트 클래스 첫번째 예제를 제가 제대로 이해하지 못하고 있는건가요?

                      class Student{
                      String name;
                      Student(String name){
                      this.name = name;
                      }
                      public boolean equals(Object obj) {
                      Student _obj = (Student)obj;
                      return name == _obj.name;
                      }
                      }

                      class ObjectDemo {

                      public static void main(String[] args) {
                      Student s1 = new Student("kareina");
                      Student s2 = new Student("kareina");
                      System.out.println(s1 == s2);
                      System.out.println(s1.equals(s2));

                      }

                      }

                      이 소스요.

                      오버라이딩 하는 부분에서,

                      public boolean equals(Student obj) {
                      Student _obj = obj;
                      return name == _obj.name;
                      }

                      이렇게 해도
                      s1.name == s2.name 의 결과를 리턴할 수 있지 않나요..?

                      다형성 부분이 굉장히 중요한 부분이라고 하셨고,
                      다형성 부분을 굉장히 흥미롭게 보았습니다만..

                      걱정되네요..

                      그리고 댓글 처음 올리네요.
                      항상 감사하며 강의 듣고 있습니다.
                    • 금도끼은도끼
                      댓글감사합니다 (__)

                      egoing님 댓글 사이트 참고해서 해결했습니다

                      애청자^^
                    • egoing
                      http://www.mkyong.com......de/

                      참고해보세요~
                      대화보기
                      • 금도끼은도끼
                        소스 네비게이션 자바소스 api 추적하는 법
                        window -> preferences -> JAVA -> installed JREs

                        edit -> 폴더 경로 수정 ( java jre -> jdk 폴더경로로 )

                        경로도 다바꿔줫는데도 안되네요 머가문제일가요??

                        Source not found
                        The JAR file C:\Program Files\Java\jre1.8.0_31\rt.jar has no source attachment
                        You can attach the source by clicking Attach Source below
                        이라구뜨네요
                        소스파일이 없는거 같은데 어디서 다운받을수있나요 ??
                      • Taeho Lee
                        Student(String name){
                        this.name = name;
                        }
                        요 부분을 잘 보시길...
                        대화보기
                        • bepositive1223
                          궁금한 사항이 있습니다.
                          <3/5> equals 에서

                          왜 return this.name == _obj.name; 으로 .name으로 비교를 하는거지요??

                          this.name은 s1의 값을 갖고 있는건 알겠는데...

                          왜 s2의 값을 표현하기 위해 .name이 붙었는지를 잘 모르겠습니다...
                        • 사그루
                          독학하는 저와 같은 사람들에게는 정말 많은 도움이 됩니다.
                          제 경우, 이미 egoing 님은 스승님, 대 싸부님이십니다.
                          좋은 강의 감사합니다!
                        • 프로그래밍을 잘 모르고 컴공에 진학했는데 많은 도움 받고 있습니다. 감사해요 ㅎㅎㅎ
                        • jeyul
                          리눅스에서 이클립스의 소스 네비게이션으로 Object 클래스의 소스코드가 열리지 않는다면,
                          openjdk-7-jdk 환경에서는 openjdk-7-source를 설치해 주시면 됩니다.
                          설치후 이클립스 다시 실행해 주세요.
                        • 샤핀
                          접근 제어 지시자는 오버라이딩할때 제약되지 않는 거군요.
                          더불어 protected 의 특성도 다시 공부하게 되네요. 좋은 강의 감사합니다.
                        • 샤핀
                          혹시나 강좌에 나온 소스 네비게이션 자바소스 api 추적하는 법 찾게되시는 분있을 까봐 댓글로 정리
                          window -> preferences -> JAVA -> installed JREs

                          edit -> 폴더 경로 수정 ( java jre -> jdk 폴더경로로 )

                          toString 강좌의 9분 30초 부분 참고하세요 ^^
                        • 퍼플라키시스
                          목소리도 멋지시고 말씀도 차분하시고.. 아나운서 같으세요
                          설명도 쏙쏙 들어오고...^^;
                          현직개발자인데 우연히 알게 되서 강의 잘 보고 갑니다

                          ps 다음생에는 왕자로 태어나시려고 덕을 쌓으시는지 ㅎㅎ
                        • 늦장공부
                          저희가 뭐 고생이라고 강의 끝날때마다 수고 하셨다고 하나요.. ㅎㅎ
                          저희는 앉아서 보기만 하는것 뿐인데요
                          이고잉 님이 고생이시죠^^ 화이팅하세요
                        • egoing
                          아 감사합니다. 이런 피드백이 이일을 계속하는 힘이 됩니다. ^^
                          대화보기
                          • 김씨밥세끼드셨나요
                            이번달부터 프로그래머라는 직업으로 뛰어들었습니다. 프로그래머를 하기위해 교육받았던 내용이 생각이 안나서 이곳저곳 기웃거리다가 고잉님의 오픈튜토리얼을 알게되서 좋은 공부 하고있습니다 ㅋㅋ 제가 일하는곳이 java랑 전자정부표준프레임워크를 쓰는데 다른 교육이나 책들과 비교했을때 머리에 너무 잘들어오게 설명해주셔서 평소에 갖고있는 의문들이 해소되는 느낌입니다 좋은 정보를 공유해주셔서 감사합니다.

                            ps. 얼른 배워서 직장 상사분들에게 안혼나야 겠어요 ㅋㅋ
                          버전 관리
                          egoing
                          현재 버전
                          선택 버전
                          graphittie 자세히 보기