clone(Java 방식)
clone (Java method)clone() 는 Java 프로그래밍 언어로 객체 복제를 위한 메서드입니다.Java에서는 오브젝트는 참조 변수를 통해 조작되며 오브젝트를 복사하는 연산자는 없습니다.할당 연산자는 오브젝트가 아닌 참조를 복제합니다.clone() 메서드는 이 기능을 제공하지 않습니다.
개요
카피 기능을 필요로 하는 클래스는, 카피 기능을 실장하기 위한 몇개의 방법을 실장할 필요가 있습니다.이 기능은 어느 정도 "에 의해 제공됩니다.Object.clone()".
clone()카피 컨스트럭터처럼 동작합니다.통상, 이 콜은clone()최종적으로 도달할 때까지 그 사본 등을 입수하는 슈퍼클래스의 방법Object의clone()방법.스페셜clone()기본 클래스의 메서드 Object에 오브젝트를 복제하기 위한 표준 메커니즘을 나타냅니다.
학급 Object의clone()method는 클래스 및 값이 동일한 모든 필드의 오브젝트 복사본을 만들고 반환합니다.하지만,Object.clone()던지다CloneNotSupportedException오브젝트가 마커 인터페이스를 구현하는 클래스의 인스턴스가 아닌 한 Cloneable.
디폴트 실장Object.clone()가 얕은 복사를 수행합니다.클래스가 딥 카피나 다른 커스텀 동작을 필요로 하는 경우는, 그 자체를 실장할 필요가 있습니다.clone()superclass에서 복사본을 가져온 후 메서드를 지정합니다.
호출 구문clone자바에서는 (전제로)objpublic이 있는 클래스 유형의 변수입니다.clone()방법):
물건 알았다. = obj.클론(); 또는 일반적으로
마이클래스 알았다. = (마이클래스) obj.클론(); 일반을 할당하는 데 필요한 타이프캐스팅을 제공합니다.Object반환된 레퍼런스clone에 대한 참조MyClass물건.
설계상의 한 가지 단점은clone()방법은 반환 타입이clone()이Object를 적절한 타입으로 명시적으로 되돌릴 필요가 있습니다.단, 덮어쓰기clone()적절한 유형을 반환하는 것이 바람직하며 클라이언트에 주조할 필요가 없습니다(J2SE 5.0 이후 공변량 반환 유형을 사용).
또 다른 단점은 대부분의 경우 에 접속할 수 없다는 것입니다.clone()추상형 메서드Java의 대부분의 인터페이스 및 추상 클래스는 공개를 지정하지 않습니다.clone()방법.그 결과, 많은 경우clone()method는 객체의 실제 클래스를 알고 있는 경우에만 사용할 수 있으며, 이는 가능한 가장 일반적인 유형을 사용하는 추상화 원리에 반합니다.예를 들어, 어떤 사용자가ListJava에서 참조를 호출할 수 없습니다.clone()그 점에 관해서는Listno public을 지정합니다.clone()방법.의 실제 실장List맘에 들다ArrayList그리고.LinkedList일반적으로 모두 가지고 있다clone()메서드 자체이지만 오브젝트의 실제 클래스 타입을 가지고 다니는 것은 불편하고 좋지 않은 추상화입니다.
대체 수단
에 대한 대안이 있다.clone()특히 복사 생성자(동일한 클래스의 다른 인스턴스를 매개 변수로 받아들이는 생성자) 또는 공장 메서드를 사용합니다.복제 객체의 구체적인 유형을 미리 알 수 없는 경우에는 이러한 방법이 항상 적절하지는 않습니다.(단,clone()대부분의 추상적인 클래스는 대중을 구현하지 않기 때문에 같은 이유로 적절하지 않은 경우가 많다.clone()메서드)를 참조해 주세요.
또, 클론을 사용하는 대신에 시리얼화 및 시리얼화 해제를 사용하는 방법도 있습니다.
싱글톤 패턴
싱글톤 패턴을 사용하여 클래스를 작성할 경우 해당 클래스의 인스턴스는 한 번에1개만 존재할 수 있습니다.따라서 클래스에서 복제본을 만들 수 없습니다.이를 방지하기 위해 이 명령어를 덮어쓸 수 있습니다.clone()다음 코드를 사용하여 메서드를 지정합니다.
일반의 물건 클론() 던지다 지원되지 않는 클론예외. { 던지다 신규 지원되지 않는 클론예외.(); } 이는 슈퍼클래스가 퍼블릭을 구현하는 경우에만 필요합니다.clone()메서드 또는 서브클래스가 이 클래스의 서브클래스를 사용하지 않도록 합니다.clone()복사본을 얻는 방법.클래스는 보통 일반인을 상속하지 않습니다.clone()방법Object공개하지 않다clone()방법, 그래서 일반적으로 기능하지 않는 것을 명시적으로 구현할 필요가 없다.clone()방법.
클래스 계층
모든 유형의 적절한 복제 가능한 개체를 제공하려면 clone() 메서드를 올바르게 선언하고 Object.clone()에 설명된 규칙에 따라 올바르게 구현해야 합니다.
1) 복제할 필요가 있는 모든 유형은 자체 클래스에 public clone() 메서드 또는 부모 클래스 중 하나에 public 액세스 가능한 clone() 메서드가 있어야 합니다.
예:
유형 Y의 varY1에서 clone()을 호출하려면 Y 또는 Y의 부모가 공개적으로 접근 가능한 clone() 메서드를 선언해야 합니다.여기서 public clone() 메서드를 제공하는 것은 부모 클래스 X입니다.
일반의 학급 X 용구 복제 가능 { 일반의 X 클론() 던지다 지원되지 않는 클론예외. { 돌아가다 (X) 잘 하는 군요.클론(); } } 일반의 학급 Y 확장 X { } 일반의 학급 Z 확장 Y { } 일반의 학급 테스트 1 { 일반의 무효 기능.() 던지다 지원되지 않는 클론예외. { Y 변동 Y1 = 신규 Z(); Y 변수 Y2 = (Y) 변동 Y1.클론(); } } 2) clone()을 구현하는 모든 클래스는 super.clone()을 호출하여 클론된 오브젝트 참조를 취득해야 합니다.클래스에 복제해야 하는 오브젝트 참조가 있는 경우(예를 들어 딥 복사 시)에는 clone() 메서드는 오브젝트를 반환하기 전에 오브젝트에 필요한 변경을 수행해야 합니다(Object.clone()은 원래 오브젝트의 정확한 복사본을 반환하므로 컬렉션이나 어레이 등의 모든 가변 필드는 o 간에 공유됩니다.riginal 및 copy(대부분의 경우 기대하지도 않고 바라지도 않습니다)
예:
클래스 Z에는 오브젝트 참조가 포함되어 있기 때문에 클래스 Z의 clone() 메서드는 원본의 딥 복사본을 반환하기 위해 해당 오브젝트 참조도 복제합니다.
일반의 학급 X 용구 복제 가능 { 일반의 X 클론() 던지다 지원되지 않는 클론예외. { 돌아가다 (X) 잘 하는 군요.클론(); } } 일반의 학급 Y 확장 X { } 일반의 학급 오브젝트 ABc 용구 복제 가능 { 일반의 오브젝트 ABc 클론() 던지다 지원되지 않는 클론예외. { 돌아가다 (오브젝트 ABc) 잘 하는 군요.클론(); } } 일반의 학급 Z 확장 Y { 사적인 오브젝트 ABc 일부 ABC; 일반의 Z 클론() 던지다 지원되지 않는 클론예외. { Z 새로운 = (Z) 잘 하는 군요.클론(); 새로운.일부 ABC = 일부 ABC.클론(); 돌아가다 새로운; } } 일반의 학급 테스트 1 { 일반의 무효 기능.() 던지다 지원되지 않는 클론예외. { Y 변동 Y1 = 신규 Z(); Y 변수 Y2 = (Y) 변동 Y1.클론(); } } 함정
계층 내의 모든 클래스가 다음을 구현한 경우clone()메서드. 클로닝 시 이들 함수가 모두 호출되어 오버헤드가 추가됩니다.여러 번 반복하면 이 오버헤드가 커질 수 있습니다.
복잡한 객체 그래프의 경우 재귀 참조가 존재할 때 심층 복사가 문제가 될 수도 있습니다.
같은 오브젝트의 복사본을 여러 개 띄우는 것이 항상 적절한 것은 아닙니다.특정의 목적이clone()구현은 소비자에 의해 완전히 이해되지 않으며, 의도하지 않게 "단일 객체, 다중 참조" 패러다임을 깨뜨릴 수 있습니다.
최종 필드
일반적으로.clone()와 호환되지 않습니다.final[ ]를 클릭합니다.왜냐면clone()는 기본적으로 디폴트 컨스트럭터(인수가 없는 컨스트럭터)입니다.를 할당할 수 없습니다.final내부 필드clone()method: 컴파일러 오류가 결과입니다.필드의 값이 불변의 오브젝트인 경우, 이것은 괜찮습니다.「컨스트럭터」가 참조를 카피하면, 오리지날과 그 클론 모두 같은 오브젝트를 공유할 수 있습니다.
단, 값이 가변 객체인 경우에는 깊이 복사해야 합니다.한 가지 해결방법은 다음 중 하나를 제거하는 것입니다.final필드로부터의 수식어가 부여한 이점을 포기합니다.
이 때문에 일부 프로그래머는 계층 내의 오브젝트를 Serializable로 하고 오래된 오브젝트를 Serializable로 한 후 결과 비트스트림에서 새로운 오브젝트를 생성하여 복사본을 만들 것을 제안합니다.이러한 오브젝트는 최종 데이터 멤버를 올바르게 처리하지만 속도가 상당히 [1]느립니다.
또는 현재 오브젝트 필드에서 완전히 새로운 오브젝트를 반환할 수 있습니다.이러한 오브젝트는 처음에 컨스트럭터를 호출하고 나중에 최종 이외의 필드를 할당할 수 있습니다.또 다른 방법은 실제로 아이디어를 공식화하는 것입니다. 즉, 인스턴스를 사용하는 복사 생성자를 만드는 것입니다.사실 그것은 일부 사람들에 의해 복제보다 권장되는 것이다.[2]
레퍼런스
- ^ Miller, Dave (August 6, 1999). "Java Tip 76: An alternative to the deep copy technique". JavaWorld. Retrieved 2020-07-14.
- ^ Clone() vs Copy Constructor - Java, StackOverflow에서 권장되는
외부 링크
- McManus, Eamonn (April 4, 2007). "Cloning Java objects using serialization". Eamonn McManus's Blog. java.net. Archived from the original on August 13, 2010. Retrieved 2010-11-16.
- Bloch, Joshua (2008). Effective Java: A Programming Language Guide. The Java Series (2nd ed.). Addison-Wesley. ISBN 0-321-35668-3.
- "Avoid clone". Collected Java Practices. Hirondelle Systems. 2009. Retrieved 2009-07-31.
- "Object (Java Platform SE 6)". Java Platform Standard Ed. 6. Sun Microsystems, Inc. 2008. Retrieved 2009-07-31.
- Roulo, Mark (January 1, 1999). "How to avoid traps and correctly override methods from java.lang.Object". JavaWorld. Retrieved 2020-07-14. - 클론 방식 구현의 기본에 대해 설명합니다.
- Java 클로닝 튜토리얼