본문 바로가기
Java

Object clone() 정의, 활용

by solbangool 2024. 5. 20.
728x90
반응형

java object를 공부하다보면 항상 만나게 되는 clone, 깊은 복사를 해준다는 것까진 알고 있는세 상세한 내용을 몰라 활용할 수 없어서 다시한번 정리해본 개념.

 

clone 메소드

  1. 인스턴스가 스스로를 복사하기 위해 사용
  2. Cloneable 인터페이스 구현 권장
  3. 깊은 복사는 직접 오버라이드하여 구현해주어야 함

➰ 알면 좋은 내용

  1. 복제의 유형:
    • 깊은 복사를 수행할 때, 모든 필드가 원시 타입이거나 불변 객체인 경우에는 처리 필요x 
    • 가변 객체를 포함하는 경우에는 해당 객체도 복제 필요
    •  
    • 더보기
      ▶ 객체의 모든 부분이 변경되지 않는다면, 그냥 복사해서 새로운 객체를 만들면 됨
      가변 객체 : 객체가 생성된 후, 그 상태를 변경할 수 있는 객체(ex, ArrayList나 HashMap과 같은 컬렉션) 이 경우, 복제본과 원본이 독립되어야 함. 그렇지 않으면 하나의 객체를 변경할 때 다른 객체에도 영향!
  2. clone() 메서드 오버라이딩:
    • clone() 메서드를 오버라이딩할 때에는 반드시 super.clone()을 호출하여 기본 복제 동작을 수행.
    • 그 후에 추가적인 필드를 깊은 복사하여 복제된 객체를 완성해야 합니다.
    • 더보기
      super.clone()  : 얕은 복사를 통해 객체의 필드들을 복제하는 것을 의미
  3. 불변 클래스와 clone():
    • 불변 클래스의 경우 복제가 필요하지 않을 수 있음
    • 불변 객체의 경우 상태가 변경될 수 없으므로, 복제된 객체를 따로 만들지 않고 그대로 사용해도 무방
    • 불변 클래스가 무엇인가?
    • 더보기
      String str = "Hello";
      str.concat(" World"); // "Hello World"를 반환하지만, str은 여전히 "Hello"입니다.

      String 클래스: Java의 String 클래스는 불변 클래스입니다. 한 번 생성된 문자열은 변경할 수 없음!

       

      LocalDate date = LocalDate.of(2022, 5, 20);
      date.plusDays(1); // 새로운 LocalDate 객체를 반환하지만, date는 여전히 2022-05-20입니다.

      LocalDate 클래스: Java 8부터 도입된 LocalDate 클래스는 불변 클래스, 날짜를 나타내는 객체를 생성한 후에는 그 날짜를 변경할 수 없음!

       

  4. Cloneable 인터페이스의 주의점:
    • Cloneable 인터페이스를 구현하면 복제 가능
    • 단, 실제로는 아무런 메서드도 제공하지 않음
    • 따라서 Cloneable 인터페이스를 구현하더라도 clone() 메서드를 직접 구현해야 함
    • 더보기
      Cloneable 인터페이스 : 마커 인터페이스(marker interface)
      아무런 메서드도 정의되어 있지 않음!

      단, 인터페이스를 구현하는 클래스에서는 Object 클래스에 정의된 clone() 메서드를 호출하여 객체를 복제할 수 있음.

      CloneNotSupportedException 발생하는 경우,
      해당 클래스에서 clone() 메서드를 오버라이딩하지 않은 것..! 
      (Cloneable 인터페이스를 구현하더라도 복제를 위한 clone() 메서드를 직접 구현해야 하므로)

 


➰ 샘플 예제

Cloneable 인터페이스를 구현하고 clone() 메서드를 오버라이딩하여 복제를 수행하는 간단한 예제

 

1️⃣MyClass라는 클래스를 정의 후 Cloneable 인터페이스를 구현

2️⃣clone() 메서드를 오버라이딩하여 super.clone()을 호출하여 얕은 복사를 수행하는 방식!

class MyClass implements Cloneable {
    private int number;
    private String text;

    public MyClass(int number, String text) {
        this.number = number;
        this.text = text;
    }

    // clone() 메서드 오버라이딩
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    public int getNumber() {
        return number;
    }

    public String getText() {
        return text;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public void setText(String text) {
        this.text = text;
    }
}

public class Main {
    public static void main(String[] args) {
        MyClass original = new MyClass(10, "Hello");

        try {
            // 객체 복제
            MyClass cloned = (MyClass) original.clone();

            // 복제된 객체의 상태 변경
            cloned.setNumber(20);
            cloned.setText("World");

            // 원본 객체와 복제된 객체의 상태 비교
            System.out.println("Original: " + original.getNumber() + ", " + original.getText());
            System.out.println("Cloned: " + cloned.getNumber() + ", " + cloned.getText());
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
    }
}
반응형

댓글