>  기사  >  Java  >  Java의 객체 복제(Clone) 튜토리얼 예시

Java의 객체 복제(Clone) 튜토리얼 예시

零下一度
零下一度원래의
2017-07-19 10:00:011486검색

Part II<br>

객체 복제에 관해 이야기하려면 객체를 복제해야 하는 이유에 대해 이야기해야 합니다. Java의 모든 객체는 힙에 저장되며 힙은 전역적으로 공유됩니다. 즉, 동일한 Java 프로그램의 서로 다른 메소드가 객체에 대한 참조를 얻을 수 있는 경우 리퍼러는 객체의 내부 데이터를 마음대로 수정할 수 있습니다(객체의 내부 데이터가 get/set 메소드를 통해 노출되는 경우). . 때때로 우리가 작성하는 코드는 호출자가 개체의 복사본 하나만 가져오기를 원합니다(즉, 내용이 정확히 같지만 메모리에 그러한 개체가 두 개 있는 개체). 이를 수행할 수 있는 방법이 있습니까? 물론 클론입니다.

3부

우선, 우리는 프로그래머이고 당연히 프로그래머의 언어로 소통합니다.

import java.util.Date;
public class User implements Cloneable {
	private String username;
	private String password;
	private Date birthdate;
	public User(String username, String password, Date birthdate) {
		this.username = username;
		this.password = password;
		this.birthdate = birthdate;
	}
	@Override
	protected Object clone() throws CloneNotSupportedException {
		return super.clone();
	}
	@Override
	public int hashCode() {
		// 省略equals的实现(可用eclipse自动生成)
	}
	@Override
	public boolean equals(Object obj) {
		// 省略equals的实现(可用eclipse自动生成)

위의 코드는 User 클래스를 빌드하고 java.lang.Cloneable 인터페이스를 구현합니다. 이름에서 알 수 있듯이 Cloneable은 이 클래스를 복제할 수 있음을 의미합니다.

먼저 java.lang.Cloneable 인터페이스가 무엇인지 살펴보겠습니다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋ rreee

	}
	// 省略一大堆get/set方法
}
놀리지 마세요. 예, 많은 닭 내장을 제외하고 이 인터페이스는 메소드 서명을 정의하지 않습니다. 즉, 객체를 복제하고 싶지만 메서드를 제공하지 않습니다. 그럼 무엇을 해야 할까요? 두려워하지 마십시오. 우리에게는 여전히 전능한 Object 클래스가 있습니다. 그가 모든 클래스의 조상(신과 같은 존재)임을 잊지 마십시오. 무슨 일이 있을 때마다 가서 인사해야 합니다. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 … e

/*
 * @(#)Cloneable.java	1.17 05/11/17
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package java.lang;
/**
 * A class implements the Cloneable interface to
 * indicate to the {@link java.lang.Object#clone()} method that it
 * is legal for that method to make a
 * field-for-field copy of instances of that class.
呵呵,又是一大串的鸡肠,别以为我是来凑字数的这些ت是Sun公主Java开发人员더 많은 내용이 있습니다. 말을 덜 하세요.

그렇습니다. 그것은 참으로 심오한 것이지만 우리는 여전히 그것을 활용해야 합니다. 더욱이, 그의 방법은 보호받고 있으며, 그는 우리에게 이점을 이용하라고 분명히 요구하고 있습니다.

아래 테스트 코드를 계속해서 살펴보세요. ReRrreerreeerrreerreeerrreerreeerrreerreeerrreerreeerrreerreeerrreerreerreerreerreerreeeee

방법은 소이고, 실행 결과는 우리의 기대에 부합합니다. 주소는 다르지만 내용은 같습니다.

파트 IV

위의 예를 통해 객체를 복제하는 데 실제로 두 단계가 있음을 알 수 있습니다.

1 클래스가 java.lang.Cloneable 인터페이스를 구현하도록 합니다.

2. 재정의합니다. (재정의) Object 클래스의 clone() 메서드.

그런데 정말 그렇게 간단할까요? 아래 코드를 다시 살펴보세요.

 *
 * Invoking Object's clone method on an instance that does not implement the
 * Cloneable interface results in the exception
 * CloneNotSupportedException being thrown.
 *
 * By convention, classes that implement this interface should override
 * Object.clone (which is protected) with a public method.
 * See {@link java.lang.Object#clone()} for details on overriding this
 * method.
 *
 * Note that this interface does not contain the clone method.
 * Therefore, it is not possible to clone an object merely by virtue of the
 * fact that it implements this interface.  Even if the clone method is invoked
 * reflectively, there is no guarantee that it will succeed.
 *
 * @author  unascribed
 * @version 1.17, 11/17/05
 * @see     java.lang.CloneNotSupportedException
 * @see     java.lang.Object#clone()
 * @since   JDK1.0

위에서는 User 클래스의 개체를 보유하는 Administrator 클래스를 정의합니다. 다음으로 관리자 개체 복제의 효과를 살펴보겠습니다.

rreee
 */
public interface Cloneable {
rrree
}
/*
 * @(#)Object.java	1.73 06/03/30
 *
 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package java.lang;
/**
rrree

헤헤헤! 문제가 발생했습니다. Java는 마스터하기가 너무 쉽습니다!

여기서 얕은 클론과 깊은 클론이라는 두 가지 전문 용어를 소개할 수 있습니다. 소위 얕은 복제는 이름에서 알 수 있듯이 매우 피상적인 복제입니다. 관리자 개체를 복제하려면 해당 개체 자체와 해당 개체에 포함된 모든 개체의

참조 주소

만 복제합니다.

그리고 깊은 복제는 얕은 복제가 아닙니다. 자체에 포함된 모든

객체 인스턴스

를 포함하여 자체를 제외한 모든 객체를 복제합니다. 심층 복제 수준은 특정 요구에 따라 결정됩니다. "N 수준 복제"라는 말도 있습니다.

단, 얕은 복제든 깊은 복제이든 모든 기본 유형 데이터는 원래 값으로 복제됩니다. 결국, 그것들은 객체가 아니며 힙에 저장되지 않습니다. 참고: 기본 데이터 유형에는 해당 래퍼 클래스가 포함되지 않습니다.

객체를 완전 복제하려면 관리자 클래스를 다음과 같이 수정할 수 있습니다.

 * Class Object is the root of the class hierarchy.
 * Every class has Object as a superclass. All objects,
 * including arrays, implement the methods of this class.
 *
 * @author  unascribed
 * @version 1.73, 03/30/06

Boolean이 값을 캐시하므로 Boolean 개체를 복제할 필요가 없습니다. 그리고 Boolean 클래스는 java.lang.Cloneable 인터페이스를 구현하지 않습니다.

파트 V

1. 让该类实现java.lang.Cloneable接口;

2. 确认持有的对象是否实现java.lang.Cloneable接口并提供clone()方法;

3. 重写(override)Object类的clone()方法,并且在方法内部调用持有对象的clone()方法;

4. ……

5. 多麻烦啊,调来调去的,如果有N多个持有的对象,那就要写N多的方法,突然改变了类的结构,还要重新修改clone()方法。

难道就没有更好的办法吗?

Part VI

接下来要重点介绍一下使用java.lang.Serializable来实现对象的深度克隆。

首先,我们编写一个工具类并提供cloneTo()方法。

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public abstract class BeanUtil {
	@SuppressWarnings("unchecked")
	public static  T cloneTo(T src) throws RuntimeException {
		ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
		ObjectOutputStream out = null;
		ObjectInputStream in = null;
		T dist = null;
		try {
			out = new ObjectOutputStream(memoryBuffer);
			out.writeObject(src);
			out.flush();
			in = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray()));
			dist = (T) in.readObject();
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			if (out != null)
				try {
					out.close();
					out = null;
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			if (in != null)
				try {
					in.close();
					in = null;
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
		}
		return dist;
	}
}

看不懂,没关系,直接拿去用就可以了。嘻嘻。

接下来我们测试一下是否能通过这个工具来实现深度克隆。

又是这个可爱的TestCase,可怜的每次都要动他……

import java.util.Date;
import org.junit.Test;
public class TestCase {
<br>
	@Test
	public void testCloneTo() {
		Administrator src = new Administrator(new User("Kent", "123456", new Date()), true);
		Administrator dist = BeanUtil.cloneTo(src);
<br>
		System.out.println(src == dist);			// false
		System.out.println(src.equals(dist));		// true
<br>
		System.out.println(src.getUser() == dist.getUser());		//false ! Well done!
		System.out.println(src.getUser().equals(dist.getUser()));	//true
	}
<br>
}

好了,无论你的对象有多么的复杂,只要这些对象都能够实现java.lang.Serializable接口,就可以进行克隆,而且这种克隆的机制是JVM完成的,不需要修改实体类的代码,方便多了。

위 내용은 Java의 객체 복제(Clone) 튜토리얼 예시의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.