programing

Java: 인스턴스 상세 복제/복사에 권장되는 솔루션

prostudy 2022. 6. 25. 20:27
반응형

Java: 인스턴스 상세 복제/복사에 권장되는 솔루션

자바에서 인스턴스의 딥 클론/복사를 하는 권장 방법이 있는지 궁금합니다.

3가지 해결책이 있는데 몇 가지를 놓쳤을 수 있으니 당신의 의견을 듣고 싶습니다.

편집: Bohzo 프로포지톤을 포함시키고 질문을 구체화합니다.이것은 얕은 클로닝보다는 깊은 클로닝에 관한 것입니다.

직접 실행:

속성 뒤에 수동 속성으로 복제를 코드화하고 가변 인스턴스도 복제되는지 확인합니다.
라이선스:
- 수행 내용 제어
실행 - 퀵 실행
삭제:

발생, 가능 속성) - "(복사/실패), "실패", "실패", "실패"

반사 사용:

독자적인 리플렉션툴이나 외부 도우미(jakarta common-beans 등)를 사용하면, 1행으로 작업을 실시하는 범용 카피 방법을 간단하게 작성할 수 있습니다.
라이선스:
- 쓰기 쉽다
없음 - 유지 보수 없음 - 유지 보수 없음
삭제:
에 대한 가 덜하다. - 무슨 일이 일어나는지 덜하다.
- - 이 서브오브젝트도 복제하지 않는 경우.
가 느리다 - 실행 속도가 느리다

클론 프레임워크 사용:

하세요. : 음음음 다다 、 다다다다다 다다다。
Serialization
딥 Java

★★

라이선스:
-반사-반사-반사-반사-반사-반사와똑같다
이 복제될지에 더 을 가지고 있습니다. - 복제될지에 대한 통제력을 강화합니다.
삭제:
한 인스턴스는 됩니다. - 층 、 계 、 - 、 - 、 - 、 - - - - - - - - - 。
수 . - 실행이 느릴 수 있습니다.

런타임에 클론을 쓰기 위해 바이트 코드 계측을 사용합니다.

javassit, BCEL 또는 cglib을 사용하여 한 손으로 쓴 것과 같은 속도로 전용 클론을 생성할 수 있습니다.이 목적을 위해 이 도구들 중 하나를 사용하는 lib를 아는 사람이 있습니까?

가가 여기 것? ??
떤떤것 ?을 ?? ???? ???

고마워요.

전체 개체 계층 복제의 경우:

  • commons-lang Serialization Utils - 시리얼라이제이션 사용 - 모든 클래스가 제어 하에 있으며 강제로 구현할 수 있는 경우Serializable.

  • Java Deep Cloning Library - 리플렉션 사용 - 클론하고 싶은 클래스 또는 오브젝트가 제어 불능(서드파티 라이브러리)으로 구현이 불가능한 경우Serializable 「」를 실장하고 않은 Serializable.

얕은 복제(첫 번째 수준 속성만 복제):

Do-it-Yourself 옵션을 일부러 생략했습니다.위의 API는 무엇을 복제할 것인지 무엇을 복제하지 않을 것인지를 적절하게 제어합니다(예를 들어, 사용).transient, 또는String[] ignoreProperties따라서 바퀴를 재창조하는 것은 바람직하지 않습니다.

Joshua Bloch의 책에는 "Item 10: Override Clone Judiciously"라는 제목의 장 전체가 있는데, 이 장에서는 대부분의 경우 클론을 덮어쓰는 것이 왜 나쁜 생각인지에 대해 설명합니다. 왜냐하면 클론의 자바 사양은 많은 문제를 일으키기 때문입니다.

그는 몇 가지 대안을 제시합니다.

  • 컨스트럭터 대신 공장 패턴을 사용합니다.

         public static Yum newInstance(Yum yum);
    
  • 복사 생성자 사용:

         public Yum(Yum yum);
    

Java의 모든 컬렉션 클래스는 복사 컨스트럭터를 지원합니다(예를 들어 새로운 ArrayList(l);).

버전 2.07 Kryo는 얕은/깊은 복제를 지원합니다.

Kryo kryo = new Kryo();
SomeClass someObject = ...
SomeClass copy1 = kryo.copy(someObject);
SomeClass copy2 = kryo.copyShallow(someObject);

Kryo는 속도가 빠릅니다.및 그들의 페이지에서 Kryo를 생산에 사용하는 회사의 목록을 찾을 수 있습니다.

메모리에서 XStream to XML/fromXML 을 사용합니다.매우 빠르고, 오랫동안 존재해 왔으며, 강해지고 있습니다.개체는 직렬화할 필요가 없으며 XStream은 사용할 수 있지만 리플렉션도 필요하지 않습니다.XStream은 동일한 개체를 가리키는 변수를 식별할 수 있으며 실수로 인스턴스의 전체 복사본을 두 개 만들지 않습니다.그와 같은 많은 세부사항들이 수년간에 걸쳐서 결정되었다.나는 그것을 몇 년 동안 사용해 왔고 그것은 아주 좋다.그것은 당신이 상상하는 것만큼 사용하기 쉽습니다.

new XStream().toXML(myObj)

또는

new XStream().fromXML(myXML)

복제하려면

new XStream().fromXML(new XStream().toXML(myObj))

보다 간결하게:

XStream x = new XStream();
Object myClone = x.fromXML(x.toXML(myObj));

복잡한 오브젝트나 퍼포먼스가 중요하지 않은 경우에는 gson을 사용하여 오브젝트를 json 텍스트로 시리얼화한 후 텍스트를 역직렬화하여 새로운 오브젝트를 가져옵니다.

반사에 기초한 gson은 대부분의 경우 작동하지만 다음 사항은 제외한다.transient필드가 복사되지 않고 원인과 함께 순환 참조가 있는 객체가 복사되지 않습니다.StackOverflowError.

public static <ObjectType> ObjectType Copy(ObjectType AnObject, Class<ObjectType> ClassInfo)
{
    Gson gson = new GsonBuilder().create();
    String text = gson.toJson(AnObject);
    ObjectType newObject = gson.fromJson(text, ClassInfo);
    return newObject;
}
public static void main(String[] args)
{
    MyObject anObject ...
    MyObject copyObject = Copy(o, MyObject.class);

}

경우에 따라 다르지요.

속도를 위해 DIY를 사용합니다.방탄에는 반사를 사용합니다.

참고로 일부 개체는 오버라이드된 직렬화 메서드(readObject/writeObject)를 제공할 수 있으며 오류가 발생할 수 있으므로 직렬화는 refl과 동일하지 않습니다.

좋은 해시 코드()와 등가() 메서드를 조합하여 유닛 테스트에서 쉽게 증명할 수 있는 DIY 방법을 추천합니다.

Object.clone()을 재정의하고 먼저 super.clone()을 호출한 다음 전체 참조에서 ref = ref.clone()을 호출하는 것이 좋습니다.어느 정도 Do it yourself 접근 방식이지만 코딩이 다소 덜 필요합니다.

딥 클로닝 구현 이렇게 클로닝하는 모든 클래스에서 시리얼 가능

public static class Obj implements Serializable {
    public int a, b;
    public Obj(int a, int b) {
        this.a = a;
        this.b = b;
    }
}

그리고 다음 기능을 사용합니다.

public static Object deepClone(Object object) {
    try {
        ByteArrayOutputStream baOs = new ByteArrayOutputStream();
        ObjectOutputStream oOs = new ObjectOutputStream(baOs);
        oOs.writeObject(object);
        ByteArrayInputStream baIs = new ByteArrayInputStream(baOs.toByteArray());
        ObjectInputStream oIs = new ObjectInputStream(baIs);
        return oIs.readObject();
    }
    catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}

이렇게요.Obj newObject = (Obj)deepClone(oldObject);

언급URL : https://stackoverflow.com/questions/2156120/java-recommended-solution-for-deep-cloning-copying-an-instance

반응형