programing

Java에서의 클론 가능 기능 및 사용 방법

goodjava 2022. 11. 30. 21:16

Java에서의 클론 가능 기능 및 사용 방법

다음 사항을 알고 싶습니다.

  1. Cloneable 수 것은 클론이나 만들 수 입니다.Cloneable인터페이스입니다.그것을 하는 것의 장점과 단점은 무엇입니까?
  2. 개체가 복합 개체인 경우 재귀 복제는 어떻게 수행됩니까?

에 먼저 할 Cloneable용하사

는 매우 .Cloneable아, 、 노도 、 어없어어

대신 Apache-Commons(딥 클론) 또는 (Shallow-Clone)과 같은 다른 옵션을 사용하거나 단순히 복사 생성자를 사용합니다.

Josh Bloch의 복제에 대한 견해는 여기를 참조하십시오.Cloneable이는 접근법의 많은 단점을 설명해 줍니다.(Joshua Bloch는 Sun의 직원이었으며 수많은 Java 기능 개발을 주도했습니다.)

복제 가능 자체는 유감스럽게도 마커 인터페이스일 뿐입니다.즉, clone() 메서드는 정의되어 있지 않습니다.

즉, 보호된 Object.clone() 메서드의 동작을 변경하여 Clone Not Supported를 슬로우합니다.복제 가능을 구현하지 않고 구현 가능한 클래스에 대해 멤버별 얕은 복사를 수행하는 클래스의 예외입니다.

이것이 당신이 찾고 있는 동작이라고 해도, 그것을 공개하기 위해서는 독자적인 clone() 메서드를 실장할 필요가 있습니다.

독자적인 클론()을 실장할 때는 올바른 클래스임을 보증하는 super.clone()에 의해 작성된 오브젝트부터 시작하여 얕은 복사가 필요한 경우에 대비하여 추가 필드 채우기를 수행합니다.clone()에서 컨스트럭터를 호출하면 서브클래스가 자신의 복제 가능한 논리를 추가하는 경우 상속이 중단되기 때문에 문제가 됩니다.super.clone()을 호출하면 이 경우 잘못된 클래스의 오브젝트를 얻을 수 있습니다.

그러나 이 방법에서는 컨스트럭터에 정의되어 있을 가능성이 있는 논리는 무시됩니다.이것은 잠재적으로 문제가 될 가능성이 있습니다.

또 다른 문제는 clone()을 덮어쓰는 것을 잊은 서브클래스가 자동으로 얕은 기본 복사본을 상속한다는 것입니다.이는 (소스와 복사본 간에 공유되는) 변경 가능한 상태의 경우 원하는 것이 아닐 수 있습니다.

대부분의 개발자는 이러한 이유로 복제 가능을 사용하지 않고 복사 생성자를 구현하기만 하면 됩니다.

Cloneable의 자세한 정보와 잠재적인 함정에 대해서는 Jooshua Bloch의 Effective Java를 적극 추천합니다.

  1. 복제는 생성자 없이 개체를 구성하는 언어 외의 방법을 호출합니다.
  2. 클로닝을 수행하려면 Clone Not Supported를 사용하여 어떤 식으로든 처리해야 합니다.예외 - 또는 클라이언트 코드를 처리하는 데 방해가 됩니다.
  3. 이점은 작습니다.복사 컨스트럭터를 수동으로 작성할 필요가 없습니다.

따라서 복제 가능은 신중하게 사용하십시오.모든 것을 제대로 하기 위해 지원해야 하는 노력에 비해 충분한 혜택을 주지 못합니다.

복제는 기본적인 프로그래밍 패러다임입니다.Java가 여러 가지 방법으로 잘못 구현했다고 해서 클로닝의 필요성이 전혀 줄어들지는 않습니다.또한 얕은 곳, 깊은 곳, 혼합된 곳 등 원하는 방식으로 작동하는 클로닝을 구현하기가 쉽습니다.필요에 따라 기능에 클론이라는 이름을 사용할 수도 있고 클론 가능을 구현할 수도 없습니다.

클래스 A, B 및 C가 있다고 가정합니다.여기서 B와 C는 A에서 파생됩니다.A 타입의 오브젝트 리스트가 다음과 같은 경우:

ArrayList<A> list1;

이 목록에는 A, B 또는 C 유형의 개체가 포함될 수 있습니다.당신은 그 물건의 종류를 모른다.따라서 다음과 같이 목록을 복사할 수 없습니다.

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(new A(a));
}

오브젝트가 실제로 타입 B 또는 타입 C일 경우 올바른 복사를 얻을 수 없습니다.그리고 A가 추상적이라면?일부에서는 다음과 같이 제안하고 있습니다.

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    if(a instanceof A) {
        list2.add(new A(a));
    } else if(a instanceof B) {
        list2.add(new B(a));
    } else if(a instanceof C) {
        list2.add(new C(a));
    }
}

이건 정말 안 좋은 생각이야파생 유형을 새로 추가하면 어떻게 됩니까?B 또는 C가 다른 패키지에 있는데 이 클래스에서 액세스할 수 없다면 어떻게 해야 합니까?

원하는 것은 다음과 같습니다.

ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
    list2.add(a.clone());
}

많은 사람들이 클론의 기본 Java 구현에 문제가 있는 이유를 제시했습니다.하지만, 이러한 방법으로 쉽게 극복할 수 있습니다.

클래스 A:

public A clone() {
    return new A(this);
}

클래스 B:

@Override
public B clone() {
    return new B(this);
}

클래스 C:

@Override
public C clone() {
    return new C(this):
}

Cloneable을 구현하는 것이 아니라 동일한 함수 이름을 사용합니다.그게 싫으면 다른 걸로 해

A) 카피 컨스트럭터보다 클론의 이점이 그다지 많지 않습니다.가장 큰 것은 완전히 동일한 다이내믹 타입의 새로운 오브젝트를 작성하는 기능입니다(선언된 타입이 클론 가능하며 퍼블릭클론 메서드가 있는 것을 전제로 되어 있습니다.

B) 기본 클론은 얕은 복사본을 만듭니다.클론 구현이 변경되지 않는 한 얕은 복사본으로 유지됩니다.이것은 어려울 수 있습니다, 특히 당신의 클래스에 최종 필드가 있는 경우

Bozho의 말이 맞아, 클론은 맞히기 어려울 수 있어.카피 컨스트럭터/팩토리는 대부분의 요구에 대응합니다.

복제 가능의 단점은 무엇입니까?

복제하려는 개체에 구성이 있는 경우 복제는 매우 위험합니다.클론이 얕은 복사본을 생성하기 때문에 이 경우 발생할 수 있는 부작용에 대해 다음과 같이 고려해야 합니다.

예를 들어 DB 관련 조작을 처리하는 개체가 하나 있다고 가정합니다.예를 들어, 그 물체는Connection속성 중 하나로 오브젝트를 지정합니다.

그래서 누군가가 클론을 만들 때originalObject작성 중인 오브젝트는 예를 들어 다음과 같습니다.cloneObject여기.originalObject그리고.cloneObject에 대해 같은 참조를 가지다Connection물건.

예를 들어originalObject닫다Connection오브젝트, 이제cloneObject동작하지 않습니다.connection오브젝트는 그들 사이에 공유되었고 그것은 사실상 닫혔다.originalObject.

IOStream을 속성으로 하는 오브젝트를 복제하는 경우에도 같은 문제가 발생할 수 있습니다.

개체가 복합 개체인 경우 재귀 복제는 어떻게 수행됩니까?

복제 가능은 얕은 복사를 수행합니다.즉, 원본 객체와 복제 객체의 데이터는 동일한 참조/메모리를 가리킵니다. 딥 카피의 경우 원본 객체의 메모리에서 복제 객체의 메모리로 복사됩니다.

언급URL : https://stackoverflow.com/questions/4081858/how-does-cloneable-work-in-java-and-how-do-i-use-it