딥 클론 유틸리티 권장 사항
Java 컬렉션에 대한 딥 클로닝을위한 유틸리티가 있습니까?
- 배열
- 기울기
- 지도
참고 : 직렬화를 사용하지 않고 Object.clone () 메서드를 사용하는 일부 솔루션을 선호합니다. 내 사용자 지정 개체가 clone () 메서드를 구현하고 복제 가능한 Java 표준 클래스 만 사용할 것임을 확신 할 수 있습니다.
이전 녹색 답변이 나쁘다고 생각합니다 . 왜 물어볼 수 있습니까?
- 그것은 많은 코드를 추가합니다
- 복사 할 모든 필드를 나열하고이를 수행해야합니다.
- 이것은 clone ()을 사용할 때 Lists에서 작동하지 않을 것입니다 (이것은 HashMap에 대한 clone ()이 말하는 것입니다 :이 HashMap 인스턴스의 얕은 복사본을 반환합니다 : 키와 값은 스스로 복제되지 않습니다.) 따라서 수동으로 수행하게됩니다. 나는 울다)
아, 그리고 직렬화도 나쁘기 때문에 여기 저기 Serializable을 추가해야 할 수도 있습니다.
그래서 해결책은 무엇입니까?
Java Deep-Cloning 라이브러리 복제 라이브러리 는 객체를 딥 복제 하는 작은 오픈 소스 (apache 라이센스) Java 라이브러리입니다. 개체는 Cloneable 인터페이스를 구현할 필요가 없습니다. 사실상이 라이브러리는 모든 Java 객체를 복제 할 수 있습니다. 즉, 캐시 된 개체를 수정하지 않으려는 경우 또는 개체의 깊은 복사본을 만들려는 경우 캐시 구현에서 사용할 수 있습니다.
Cloner cloner=new Cloner();
XX clone = cloner.deepClone(someObjectOfTypeXX);
https://github.com/kostaskougios/cloning 에서 확인 하세요.
Java에서 객체를 복사하는 모든 접근 방식에는 심각한 결함이 있습니다.
복제
- clone () 메서드는 보호되어 있으므로 해당 클래스가 공용 메서드로 재정의하지 않는 한 직접 호출 할 수 없습니다.
- clone ()은 생성자를 호출하지 않습니다. 모든 생성자. 메모리를 할당하고 내부
class
필드 (를 통해 읽을 수 있음)를 할당getClass()
하고 원본 필드를 복사합니다.
clone ()에 대한 추가 문제는 Joshua Bloch의 저서 " Effective Java, Second Edition " 의 항목 11을 참조하십시오.
직렬화
직렬화는 더 나쁩니다. 그것은 많은 결점을 가지고 clone()
있고 그 다음에는 일부가 있습니다. Joshua는이 주제에 대해서만 4 개의 항목이있는 전체 장을 가지고 있습니다.
내 솔루션
내 솔루션은 내 프로젝트에 새 인터페이스를 추가하는 것입니다.
public interface Copyable<T> {
T copy ();
T createForCopy ();
void copyTo (T dest);
}
코드는 다음과 같습니다.
class Demo implements Copyable<Demo> {
public Demo copy () {
Demo copy = createForCopy ();
copyTo (copy);
return copy;
}
public Demo createForCopy () {
return new Demo ();
}
public void copyTo (Demo dest)
super.copyTo (dest);
...copy fields of Demo here...
}
}
불행히도이 코드를 모든 개체에 복사해야하지만 항상 동일한 코드이므로 Eclipse 편집기 템플릿을 사용할 수 있습니다. 장점 :
- 호출 할 생성자와 필드를 초기화하는 방법을 결정할 수 있습니다.
- 초기화는 결정적 순서로 발생합니다 (루트 클래스에서 인스턴스 클래스로).
- 기존 개체를 재사용하고 덮어 쓸 수 있습니다.
- 안전한 유형
- 싱글 톤은 싱글 톤 유지
표준 Java 유형 (컬렉션 등)의 경우이를 복사 할 수있는 유틸리티 클래스를 사용합니다. 메서드에는 플래그와 콜백이 있으므로 복사본의 깊이를 제어 할 수 있습니다.
컬렉션을 얕게 복제하는 것은 쉽지만 딥 복제를 원한다면 라이브러리가 직접 코딩하는 것보다 더 잘할 것입니다 ( 컬렉션 내부 의 요소도 복제하기를 원하기 때문입니다 ).
그냥 같은 이 대답 , 내가 사용했습니다 Cloner는 라이브러리를 특히 성능은 XStream을 상대로 테스트 (이 다음 직렬화 직렬화 복원에 의해 '복제'할 수있는)와 바이너리 직렬화. XStream은 xml과의 직렬화 속도가 매우 빠르지 만 Cloner는 복제 속도가 훨씬 빠릅니다.
0.0851 ms : xstream (직렬화 / 역 직렬화로 복제)
0.0223 ms : 이진 직렬화 (직렬화 / 역 직렬화로 복제)
0.0017 ms : 복제기
* 단순 개체 (두 필드)를 복제하는 데 걸리는 평균 시간이며 기본 공용 생성자는 없습니다. 10,000 번 실행합니다.
빠른 속도 외에도 다음은 클론을 선택해야하는 더 많은 이유입니다.
- 모든 개체의 딥 복제를 수행합니다 (자신이 작성하지 않은 개체도 포함).
- you don't have to keep your clone() method up-to-date each time you add a field
- you can clone objects that don't have a default public constructor
- works with Spring
- (optimization) doesn't clone known immutable objects (like Integer, String, etc.)
easy to use. Example:
cloner.deepClone(anyObject);
I am the creator of the cloner lib, the one that Brad presented. This is a solution for cloning objects without having to write any extra code (no need for serializable objects or impl clone() method)
It's quite fast as Brad said, and recently I uploaded a version which is even faster. Note that manually implementing a clone() method will be faster than clone lib, but then again you'll need to write a lot of code.
Cloner lib has worked quite well for me since I am using it in a cache implementation for a site with very heavy traffic (~1 million requests/day). The cache should clone approximately 10 objects per request. It is quite reliable and stable. But please be aware that cloning is not without risk. The lib can be configured to println every class instance that it clones during dev. This way you can check if it clones what you think it should clone - object graphs can be very deep and can contain references to a surprisingly large amount of objects. With clone lib, you can instruct it to not clone the objects that you don't want, i.e. singletons.
One general way to deep-clone an arbitrary collection is to serialize it to a stream, then read it back into a new collection. You'll be rehydrating completely new objects that don't have any relationship to the old ones, other than being identical copies.
Check out Bruno's answer for a link to the Apache Commons serialization utility classes, which will be very helpful if this is the route you decide to take.
One possibility is to use serialization:
Apache Commons provides SerializationUtils
I've used this cloning library and found it quite useful. Since it had a few limitations (I needed finer grained control over the cloning process: which field, in what context and how deeply should be cloned etc.), I've created an extended version of it. You control the cloning of the fields by annotating them in the entity class.
Just to get a flavour of it, here is an example class:
public class CloneMePlease {
@Clone(Skip.class)
String id3 = UUID.randomUUID().toString();
@Clone(Null.class)
String id4 = UUID.randomUUID().toString();
@Clone(value = RandomUUID.class, groups=CustomActivationGroup1.class)
String id5 = UUID.randomUUID().toString();
@Clone.List({
@Clone(groups=CustomActivationGroup2.class, value=Skip.class),
@Clone(groups=CustomActivationGroup3.class, value=Copy.class)})
Object activationGroupOrderTest = new Object();
@Clone(LongIncrement.class)
long version = 1l;
@PostClone
private void postClone(CloneMePlease original, @CloneInject CloneInjectedService service){
//do stuff with the original source object in the context of the cloned object
//you can inject whatewer service you want, from spring/guice to perform custom logic here
}
}
More details here: https://github.com/mnorbi/fluidity-cloning
There is also a hibernate specific extension in case one needs it.
Use serialization and then deserialization, but be aware that this approach works only with Serializable classes without transient fields. Also, your singletons will not be singletons anymore.
참고URL : https://stackoverflow.com/questions/665860/deep-clone-utility-recommendation
'Nice programing' 카테고리의 다른 글
VS Code에서 기본적으로 텍스트 줄 바꿈을 설정하는 방법 (0) | 2020.10.29 |
---|---|
Python 가져 오기에 대한 좋은 경험 규칙은 무엇입니까? (0) | 2020.10.29 |
MS Excel 용 JSON 형식을 CSV 형식으로 변환 (0) | 2020.10.29 |
데이터 주석의 Asp.Net Mvc 숨겨진 필드 (0) | 2020.10.29 |
NuGet.exe를 소스 제어에 추가 할 필요 방지 (0) | 2020.10.29 |