ホームページ  >  記事  >  Java  >  Java でのオブジェクトの複製 (Clone) のチュートリアルの例

Java でのオブジェクトの複製 (Clone) のチュートリアルの例

零下一度
零下一度オリジナル
2017-07-19 10:00:011522ブラウズ

パート II<br>

オブジェクトのクローン作成について話すと、なぜオブジェクトをクローンする必要があるのか​​について話さなければなりません。 Java のすべてのオブジェクトはヒープに格納され、ヒープはグローバルに共有されます。言い換えれば、同じ Java プログラムの異なるメソッドがオブジェクトへの参照を取得できる場合、リファラーはオブジェクトの内部データを自由に変更できます (オブジェクトの内部データが get/set メソッドを通じて公開されている場合)。 。私たちが作成するコードでは、呼び出し元にオブジェクトのコピーを 1 つだけ取得してもらいたいことがあります (つまり、まったく同じ内容のオブジェクトですが、メモリ内にそのようなオブジェクトが 2 つあります)。これを行う方法はありますか?もちろんクローンです。

パート III

まず第一に、私たちはプログラマーであり、もちろんプログラマーの言語でコミュニケーションを行います。

上記のコードは、User クラスを構築し、java.lang.Cloneable インターフェースを実装します。名前が示すように、Cloneable は、このクラスを複製できることを意味します。

まず、java.lang.Cloneable インターフェースが何を持っているかを見てみましょう。 ❤️そうです、多くの鶏の腸を除いて、このインターフェイスはメソッド シグネチャを定義していません。言い換えれば、オブジェクトのクローンを作成したいのですが、メソッドが提供されません。じゃあ何をすればいいの?心配しないでください、まだ全能の Object クラスが存在します。彼はすべてのクラスの祖先 (神のような存在) であることを忘れないでください。

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自动生成)
	}
	// 省略一大堆get/set方法
}
/*
 * @(#)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.
 *
 * 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
 */
public interface Cloneable {
}
/*
 * @(#)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;
/**
 * 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
 * @see     java.lang.Class
 * @since   JDK1.0
 */
public class Object {
    <br>
   // 省略N多的代码
    /**
呵呵,又是一大串的鸡肠,别以为我是来凑字数的,这些都是Sun公司Java开发人员写的技术文章,多看看話すことを減らしましょう。

はい、これは確かに奥深いものですが、それでも活用する必要があります。さらに、彼の手法は保護されており、明らかに私たちに利用するよう求めています。

引き続き以下のテストコードを見てください。

メソッド、牛です、実行結果は期待通りですアドレスは違いますが内容は同じです。

パート IV

上の例を通して、オブジェクトを複製するには実際には 2 つのステップがあることがわかります。

1. クラスに java.lang.Cloneable インターフェースを実装します。 2. オーバーライドします。 Object クラスの clone() メソッドを (オーバーライド) します。

しかし、本当にそんなに単純なのでしょうか?以下のコードをもう一度見てください。

上記は User クラスのオブジェクトを保持する Administrator クラスを定義しています。次に、Administrator オブジェクトの複製の効果を見てみましょう。 Rrereerreerrreerreerreerreerreerreerreerreerreerreerreerreerreerreerreerreerreerreerreerreerree
     * Creates and returns a copy of this object.  The precise meaning
re hehehe!何か問題が発生しました。 Java をマスターするのはとても簡単です。

ここで、浅いクローンと深いクローンという 2 つの専門用語を紹介します。

いわゆるシャロー クローンは、名前が示すように、非常に表面的なクローンです。管理者オブジェクトをクローンする場合は、それ自体とそれに含まれるすべてのオブジェクトの

参照アドレス

のみをクローンします。

そして、ディープ クローン作成はシャロー クローン作成ではありません。それ自体を除くすべてのオブジェクト (それ自体に含まれるすべての

オブジェクト インスタンス

を含む) をクローンします。ディープ クローン作成のレベルについては、特定のニーズによって決まります。「N レベル クローン作成」という言葉もあります。

ただし、浅いクローンでも深いクローンでも、すべてのプリミティブ型のデータは元の値でクローンされます。結局のところ、それらはオブジェクトではなく、ヒープに格納されません。注: 基本データ型には、対応するラッパー クラスが含まれません。

オブジェクトをディープクローンしたい場合は、次のように Administrator クラスを変更できます。

RREERREERREERREERREERREERREE

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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。