클론은 원래의 정확한 복사본. 자바에서는 본질적으로 원래 객체와 비슷한 상태의 객체를 만드는 기능을 의미합니다. Javaclone()
메서드는이 기능을 제공합니다.
이 게시물에서는 Java clone 의 중요한 측면 대부분을 살펴볼 것입니다.
Table of Contents1. What is clone?2. Java Cloneable interface and clone() method3. Shallow Copy4. Deep Copy5. Java Copy Constructors6. Deep copy with serialization7. Cloning using Apache commons8. Java clone best practices
Java clone 이란 무엇입니까?
그래서 복제는 원래 객체의 복사본을 만드는 것입니다. 그것의 사전 의미는 : “의 동일한 사본을 만드십시오”.
기본적으로 java 복제는’field by field copy’즉 Object 클래스가 clone()메소드가 호출 될 클래스의 구조에 대한 아이디어가 없기 때문입니다.
이 JVM 라고 할 때 복제,다음과 같은 작업을 수행 할
- 경우 클래스는 단지 원시 데이터 형식을 구성원이 다음 완전히 새로운 복사한 객체의 생성됩니다 그리고 새로운 객체를 복사본을 반환됩니다.
- 경우 클래스의 구성원이 포함 모든 클래스 형식을 그만 객체에 대한 참조는 그 회원들은 복사하고 따라서 회원의 참조 모두 원본 개체뿐만 아니라 복제된 객체 참조하여 동일한 개체입니다.
위의 기본 동작 외에도 항상이 동작을 재정의하고 자신을 지정할 수 있습니다. 이것은 재정의clone()
메소드를 사용하여 수행됩니다. 그것이 어떻게 행해지는지 보자.
Java Cloneable interface and clone()method
객체의 복제를 지원하는 모든 언어에는 고유 한 규칙이 있으며 java 도 마찬가지입니다. Java 는 경우,클래스 요구를 지원하는 복제 할 수 있 다음과 같은 일:
- 을 구현해야 합
Cloneable
인터페이스입니다. - 객체 클래스에서
clone()
메소드를 재정의해야합니다.
더 읽기:복제 가능 인터페이스 부분에 java
Java 문서에 대해clone()
방법은 아래 주어진(서식과 추출물)
- 첫 번째 문은 복제 된 객체가 별도의 메모리 주소 할당을 갖도록 보장합니다.
- 두 번째 문는 원본과 복제체가 있어야 같은 클래스 형식이지만,필수입니다.
- 세 번째 문은 equals()메소드를 사용하여 원래 객체와 복제 된 객체가 동일해야한다고 제안하지만 필수는 아닙니다.
예제를 통해 Java 클론을 이해합시다. 우리의 첫 번째 클래스가Employee
id
name
department
.
Department
id
name
.따라서 직원 클래스를 복제해야하는 경우 다음과 같은 작업을 수행해야합니다.
좋아요,Employee
객체를 성공적으로 복제했습니다. 그러나,기억 우리는 두 가지를 참조하여 동일한 개체에 이제 모두 변경됩니다 주체의 다른 부분에서의 응용 프로그램. 어떻게보고 싶습니까? 보자.
Oops,복제 된 객체 변경 사항도 원본에서 볼 수 있습니다. 이 방법으로 복제 된 객체는 그렇게하도록 허용되면 시스템에서 혼란을 야기 할 수 있습니다. 누구나 와서 응용 프로그램 개체를 복제하고 그가 좋아하는 것을 할 수 있습니다. 우리는 이것을 막을 수 있습니까??
대답은 예,우리는 할 수 있습니다. Java deep copy 를 만들고 copy 생성자를 사용하여이를 방지 할 수 있습니다. 우리는 나중에이 게시물에서 그들에 대해 배울 것입니다. 먼저 자바에서 딥 클로닝과 얕은 클로닝이 무엇인지 살펴 보겠습니다.
Java 얕은 복사
얕은 복제는 Java 에서”기본 구현”입니다. 에 재정의clone
방법하지 않는 경우,복제 모든 개체형(지 않은 primitives),그 다음 당신은 얕은 복사합니다.
모든 위의 예제의 얕은 복사만,우리가 있기 때문에 복제Department
Employee
clone
방법입니다. 이제 딥 클로닝을 볼 수있는 다음 섹션으로 넘어갈 것입니다.
Java Deep Copy
Deep clone 은 대부분의 경우 원하는 동작입니다. 딥 카피에서 우리는 원래 객체와 독립적 인 복제물을 만들고 복제 된 객체의 변경은 원래 객체에 영향을 미치지 않아야합니다.
자바에서 얼마나 깊은 복사가 만들어 졌는지 보자.
I modifiedEmployee
clone()
clone
Department
클래스입니다.
이제 복제 코드를 테스트하면 원하는 결과가 나오고 부서의 이름은 수정되지 않습니다.
여기서 복제 된 객체의 상태를 변경해도 원래 객체에는 영향을 미치지 않습니다.
그래서 깊은 복제는 다음과 같은 규칙의 만족을 필요로-
- 별도로 프리미티브를 복사 할 필요가 없습니다.
- 모든 멤버 클래스에서는 원래 클래스를 지원해야 합 복제 및 복제 방법의 원래 등에서의 컨텍스트를 호출해야 합
super.clone()
에 모든 멤버 클래스입니다. - 경우 모든 멤버 클래스를 지원하지 않 복제 다음에 복제 방법 중 하나 만들어야합의 새 인스턴스는 멤버 클래스와 모든 사본을 그 특성에 의해 하나 하나를 새로운 멤버 클래스 개체입니다. 이 새 멤버 클래스 객체는 복제 된 객체에 설정됩니다.
자세히보기:깊은 복제를 사용하여 메모리에서 직렬화
Java 복사본을 생성자
사본을 생성자는 특별 생성자 클래스에서는 인수한 자신의 클래스는 유형입니다. 그래서,당신이 통과 할 때 클래스의 인스턴스를 복사본을 생성자,그때 생성자를 반환하는 새로운 클래스의 인스턴스 값으로 복사에서 인수의 인스턴스입니다. 그것은 당신이 Cloneable 인터페이스로 객체를 복제하는 데 도움이됩니다.
볼 수 있습니다 이에 예:
public class PointOne {private Integer x;private Integer y;public PointOne(PointOne point){this.x = point.x;this.y = point.y;}}
이 방법은 보이는 간단하고 그것 때까지 상속입니다. 위의 클래스를 확장하여 클래스를 정의 할 때 거기에서도 비슷한 생성자를 정의해야합니다. 자식 클래스에서는 자식 특정 속성을 복사하고 인수를 수퍼 클래스의 생성자에 전달해야합니다. 어떻게 보자?
그래서,우리는 지금 괜찮습니까? 아니. 상속의 문제점은 정확한 동작이 런타임에만 식별된다는 것입니다. 그래서 이 경우에는 일부 경우 클래스는 전달된 인스턴스PointTwo
PointOne
.
이 경우PointOne
PointTwo
의 인스턴스를 인수로 전달했습니다. 볼 수 있습니다 이에 코드:
는 또 다른 방법을 만드는 복사본을 생성자를 가다 그들은 인수에서 클래스 유형을 취하고 클래스의 다른 생성자를 사용하여 새 인스턴스를 만듭니다. 그런 다음 이러한 공장 방법에 복사하는 모든 데이터 상태를 새로운 클래스의 인스턴스에서 만든 이전 단계,및 반품이 업데이트 인스턴스입니다.
직렬화가있는 Java 딥 복사
직렬화는 딥 클로닝의 또 다른 쉬운 방법입니다. 이 방법에서는 복제 할 객체를 직렬화하고 직렬화를 해제하면됩니다. 분명히 복제해야하는 객체는Serializable
인터페이스를 구현해야합니다.더 이상 진행하기 전에이 기술을 가볍게 사용하지 않도록주의해야합니다.
- 우선 직렬화는 상당히 비쌉니다. 그것은 쉽게
clone()
방법보다 백 배 더 비쌀 수 있습니다. - 둘째,모든 객체가
Serializable
인 것은 아닙니다. - 셋째,만들기 클래스가
Serializable
은 까다로운 모든 클래스에 의지를 바로 그것을 얻을 수 있습니다.
더 읽기:가이드를 구현하는 직렬화에 Java
Java 복제 SerializationUtils
Apache commons,SerializationUtils
클래스가 유틸리티 기능에 대한 깊은 복제. 당신이 관심을 느끼는 경우에 따라 자신의 공식 문서.
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.7</version></dependency>
SomeObject cloned = org.apache.commons.lang.SerializationUtils.clone(someObject);
Java 복제 모범 사례
- 지 않는 경우할 수 있는지 여부를 알 수 있습 전화
clone()
Cloneable
if(obj1 instanceof Cloneable){ obj2 = obj1.clone();}//Dont do this. Cloneable dont have any methodsobj2 = (Cloneable)obj1.clone();
- 복제중인 객체에서 생성자가 호출되지 않습니다. 결과적으로 모든 구성원이 올바르게 설정되었는지 확인하는 것은 귀하의 책임입니다. 또한 생성자의 호출을 계산하여 시스템의 객체 수를 추적하는 경우 카운터를 증가시키는 새로운 추가 장소를 얻었습니다.
익스피디아에는 취소 수수료가 없했 재교육을 위해 당신을 얻을 수 있도록에 대한 자세한 정보 Java8 복제 방식과 그것의 올바른 사용합니다. 또한 자바 클론 인터뷰 질문에 답하는 데 도움이 될 것입니다.
행복한 학습!!