java深復制
㈠ java中深克隆與淺克隆的區別
深克隆與淺克隆
大家知道,對象是互相引用的,即對象中可能包含了另一個對象的引用,舉例如:有一個Order對象,Order對象中又包含了LineItems對象,然後LineItems對象又包含了Item對象。
好了,現在我有一個Order對象order1,它包含了一個LineItems對象items,這表示的是有一個訂單order1,訂單的內容是items。
好的,現在有另一個客戶想要一份訂單,內容跟order1完全一樣,那麼在系統的邏輯層我們怎麼做呢?很簡單,order2=order1.clone(). 我們知道clone方法是在內存中生成一個新的對象,而不是只得到原對象的引用。這時候,有人說話了:「哦,明白了我們對order2的成員變數進行修改,是不會影響order1的。」 很可惜,這句話只對了一半。
假設order類有一個成員變數name,當然改變order2.name不會影響order1.name,因為他們在不同的內存區域。但是如果改變 order1.items呢?很遺憾,簡單地使用order1.clone,是會影響到order2.items的。原因很簡單,就是因為clone方法默認的是淺克隆,即不會克隆對象引用的對象,而只是簡單地復制這個引用。所以在上例中,items對象在內存中只有一個,order1和order2都指向它,任何一個對象對它的修改都會影響另一個對象。
那相對淺克隆,深克隆自然就是會克隆對象引用的對象了。也就是說,在上例中,改變order1.items並不會影響order2.items了。因為內存中有兩個一樣的items。
如果實現深克隆?
一個方法自然是重寫clone方法,添加如order.items=(LineItems)items.clone()的語句,也就是人為地添加對引用對象的復制。這個方法的缺點是如果引用對象有很多,或者說引用套引用很多重,那麼太麻煩了。業界常用的方法是使用串列化然後反串列化的方法來實現深克隆。由於串列化後,對象寫到流中,所有引用的對象都包含進來了,所以反串列化後,對等於生成了一個完全克隆的對象。絕!
這個方法的要求是對象(包括被引用對象)必須事先了Serializable介面,否則就要用transient關鍵字將其排除在復制過程中。
㈡ 什麼是深拷貝和淺拷貝
淺拷貝就是指對象復制的時候只復制一層;深拷貝是指復制對象的所有層級。
深拷貝和淺拷貝,主要是對象發生復制的時候,根據復制的層級不同來區分的。很多人在這里經常變數賦值發生混淆。對於JavaScript數組等復雜的數據類型來說,將其賦值給其它變數,其實只是復制了對象的地址給它,兩個變數指向的是同一個對象,因此普通的賦值既不是深拷貝也不是淺拷貝。
深拷貝和淺拷貝需要注意的地方就是可變元素的拷貝:
在淺拷貝時,拷貝出來的新對象的地址和原對象是不一樣的,但是新對象裡面的可變元素(如列表)的地址和原對象里的可變元素的地址是相同的,也就是說淺拷貝它拷貝的是淺層次的數據結構(不可變元素),對象里的可變元素作為深層次的數據結構並沒有被拷貝到新地址裡面去。
而是和原對象里的可變元素指向同一個地址,所以在新對象或原對象里對這個可變元素做修改時,兩個對象是同時改變的,但是深拷貝不會這樣,這個是淺拷貝相對於深拷貝最根本的區別。
㈢ java二維數組怎麼復制,,array方法行嗎麻煩給個例子。謝啦
java的多維數組的:希望採納
class C{
public static void main(String args[]){
int a[][] = {{1,2,3},{4,5,6}};
int b[][] = new int[a.length][a[0].length];
System.array(a,0,b,0,a.length); //通過array()函數拷貝數組
b[0][0] = 4; //改變數組b[0][0]的值
System.out.println("a[][]");
for(int i=0;i<2;i++){
for(int j=0;j<3;j++){
System.out.print(a[i][j]+" ");
}
System.out.println();
}
System.out.println("b[][]");
for(int i=0;i<2;i++){
for(int j=0;j<3;j++){
System.out.print(b[i][j]+" ");
}
System.out.println();
}
}
列印的結果如下:
a[][]
4 2 3
4 5 6
b[][]
4 2 3
4 5 6
而如果把上述程序中的二維數組改為一維數組,結果卻不同。程序如下:
class C{
public static void main(String args[]){
int a[] = {1,2,3};
int b[] = new int[a.length];
System.array(a,0,b,0,a.length); //通過array()函數拷貝數組
b[0] = 4; //改變數組b[0]的值
System.out.println("a[]:");
for(int i=0;i<3;i++){
System.out.print(a[i] + " ");
}
System.out.println();
System.out.println("b[]:");
for(int i=0;i<3;i++){
System.out.print(b[i] + " ");
}
}
}
列印結果如下:
a[]:
1 2 3
b[]:
4 2 3
在
第一個程序中,用b[0][0] =
4;只改變了數組b[0][0]的值,可是結果卻是數組a[0][0]的值也發生了改變。而在第二個程序中,由於是一個一維數組,改變了b[0]的
值,a[0]的值卻並沒有受到影響,所以問題可能就出在數組的維數上。第一個程序中的a 是一個數組的數組(java
中沒有多維數組的概念,只有數組的數組),同理b 也是,那麼a 含有兩個元素,第一個是指向(1,2,3)
這個數組的引用,第二個是指向(4,5,6)這個數組的引用,而arrayCopy 就是負責把數組的內容 過去的,因此 a 的內容 (2
個引用) 被 到b 中去了,因此你對b[0][0] 做修改,a 也會同樣跟著變化.
在JAVA裡面,可以用復制語句「A=B」給基本類型的數據傳遞值,但是如果A,B是兩個同類型的數組,復制就相當於將一個數組變數的引用傳遞給另一個數組;如果一個數組發生改變,那麼引用同一數組的變數也要發生改變。
JAVA中復制數組元素值的的方法指深拷貝
1 使用for循環,將數組的每個元素復制(需要將每個對象調用clone方法,才能實現真正的復制)
2 使用clone方法,得到數組的值,而不是引用
3 使用System.array方法
注意:
1.上面方法中array效率較高。
2. 以上所說的拷貝數組的方法,只是針對一維數組,對於多維數組,要在每一維用以上方法進行復制才能實現復制數組元素的值而不是引用。
3. clone 和 array對二維數組進行復制時,是淺拷貝, 即
Object[][] aa;
Object[][] bb = aa.clone();
//or bb=System.array(aa,0,bb, 0, bb.length);
則:
boolean b1 = ( aa[i] == bb[i] ); //false
boolean b2 = (aa[i][j] == bb[i][j]); //true, 可見數組元素只復制了引用。新舊數組指向相同的內存地址,(不論對象數組,還是基本類型數組)。
/**
* 數組的淺拷貝是指數組拷貝時,只拷貝了數組的地址,新舊數組指向同一數據
* 數組的深拷貝,不論數據是基本類型,還是對象類型,都是一樣的。
* 對數組來說,不一樣的地方在於,當為數組元素賦值時,基本類型值傳遞,對象類型是引用傳遞。
*
*/
Object[] a = new Object[]{"String", new Integer(1)};
Object[] b = a;
/**
* 數組深拷貝的方法有如下幾種:
* 1。 調用clone
* 2。 調用System.array
* 以上兩種對基本類型和對象類型數據效果等同。
* 3。 使用FOR循環,將數組的每個元素復制。(注意調用clone方法)
*
*/
/*
* 當數組數據是基本類型時,
*/
// int[] array = new int[]{0,1,2,3,4};
// int[] = array.clone(); //1.拷貝數據
// System.out.println( .equals(array));
// System.out.println( == array );
// for (int i = 0; i < .length; i++) {
// System.out.print( [i]+", " );
// [i]++; //2.改變新數組數據內容
// System.out.print( [i]+", " );
// System.out.println( array[i]+","); //3.不影響原始數組
// }
// System.out.println();
/*
* 當數組數據是對象類型時,
*/
// Object[] src = new Object[]{ new String("Zhao"),
// Integer.valueOf(1),
// Integer.valueOf(2),
// Integer.valueOf(3),
// Integer.valueOf(4)};
//
// Object[] dest = src.clone(); //1.拷貝數據
//
//// Object[] dest = new Object[5];
//// System.array(src, 0, dest, 0, dest.length);
//
// System.out.println( dest.equals(src));
// System.out.println( dest == src );
// for (int i = 0; i < dest.length; i++) {
// System.out.print( dest[i]+", " );
// dest[i] = new String("KE"); //2.改變新數組內容
// System.out.print( dest[i]+", " );
// System.out.println( src[i]+","); //3.不影響原始數組
// }
// System.out.println();
/**
* 對多維數組(多維基本類型數組和多維對象數組完全一致。)
*
*/
//多維基本類型數組
int[][] aa = new int[][]{
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
// //多維對象類型數組
// Object[][] aa = new Object[][]{
// { Integer.valueOf(1),Integer.valueOf(2),Integer.valueOf(3) },
// { Integer.valueOf(4),Integer.valueOf(5),Integer.valueOf(6) },
// { Integer.valueOf(7),Integer.valueOf(8),Integer.valueOf(9) }
// };
/**
* 一維數組下的深拷貝在 多維數組 只是淺拷貝!!
*/
int[][] bb = aa.clone(); //一維數組下的深拷貝,對於二維數組只是淺拷貝!!
// int[][] bb = new int[aa.length][aa[0].length];
// System.array(aa, 0, bb, 0, aa.length);
// Object[][] bb = aa.clone();
//// Object[][] bb = new Object[3][3];
//// System.array(aa, 0, bb, 0, aa.length); //一維數組下的深拷貝,對於二維數組只是淺拷貝!!
/**
* 二維數組的深拷貝的實現方式!!! 轉為一維數組拷貝。
*/
// for (int i = 0; i < bb.length; i++) { //實現深拷貝的方法!!!!!!!!!!!!
// System.array(aa[i], 0, bb[i], 0, aa[i].length);
// // bb[i] = aa[i].clone();
// }
System.out.println("## 初始 aa:" ); //1. 初始原數組
for (int i = 0; i < aa.length; i++) {
for (int j = 0; j < aa[i].length; j++) {
System.out.print(aa[i][j]+" ");
}
System.out.println( );
}
System.out.println("## bb = aa.clone() 後bb:" ); //2. 新數組(值等於原數組的值)
for (int i = 0; i < bb.length; i++) {
for (int j = 0; j < bb[i].length; j++) {
System.out.print(bb[i][j]+" ");
}
System.out.println( );
}
System.out.println("## bb改變後:" ); //3.改變新數組後
for (int i = 0; i < bb.length; i++) {
for (int j = 0; j < bb[i].length; j++) {
bb[i][j] += 10; //for 多維基本類型數組
// bb[i][j] = new String("Zhao"); //for 多維對象類型數組
System.out.print(bb[i][j]+" ");
}
System.out.println( );
}
System.out.println("## bb改變後, aa:" ); //4.輸出原數組
for (int i = 0; i < aa.length; i++) {
for (int j = 0; j < aa[i].length; j++) {
System.out.print(aa[i][j]+" ");
}
還有和c++不同,java定義int [][]a=new int[3][];是沒有問題的,c和c++後面就是必須要有維數,int a[][3];。
如果list裡面全是String[],轉為String[][],使用
(String[][]) bodyDataList.toArray(new String[bodyDataList.size()][]);這樣就能轉成功,還一直不清楚toArray(x)x裡面的東西,因為java裡面只有array對象
㈣ 如何使Java中的InputStream的深層復制
我們知道在Java中存在這個介面Cloneable,實現該介面的類都會具備被拷貝的能力,同時拷貝是在內存中進行,在性能方面比我們直接通過new生成對象來的快,特別是在大對象的生成上,使得性能的提升非常明顯。然而我們知道拷貝分為深拷貝和淺拷貝之分,但是淺拷貝存在對象屬性拷貝不徹底問題。關於深拷貝、淺拷貝的請參考這里:漸析java的淺拷貝和深拷貝
一、淺拷貝問題
我們先看如下代碼:
[java] view plain
public class Person implements Cloneable{
/** 姓名 **/
private String name;
/** 電子郵件 **/
private Email email;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Email getEmail() {
return email;
}
public void setEmail(Email email) {
this.email = email;
}
public Person(String name,Email email){
this.name = name;
this.email = email;
}
public Person(String name){
this.name = name;
}
protected Person clone() {
Person person = null;
try {
person = (Person) super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return person;
}
}
public class Client {
public static void main(String[] args) {
//寫封郵件
Email email = new Email("請參加會議","請與今天12:30到二會議室參加會議...");
Person person1 = new Person("張三",email);
Person person2 = person1.clone();
person2.setName("李四");
Person person3 = person1.clone();
person3.setName("王五");
System.out.println(person1.getName() + "的郵件內容是:" + person1.getEmail().getContent());
System.out.println(person2.getName() + "的郵件內容是:" + person2.getEmail().getContent());
System.out.println(person3.getName() + "的郵件內容是:" + person3.getEmail().getContent());
}
}
--------------------
Output:
張三的郵件內容是:請與今天12:30到二會議室參加會議...
李四的郵件內容是:請與今天12:30到二會議室參加會議...
王五的郵件內容是:請與今天12:30到二會議室參加會議...
在該應用程序中,首先定義一封郵件,然後將該郵件發給張三、李四、王五三個人,由於他們是使用相同的郵件,並且僅有名字不同,所以使用張三該對象類拷貝李四、王五對象然後更改下名字即可。程序一直到這里都沒有錯,但是如果我們需要張三提前30分鍾到,即把郵件的內容修改下:
[java] view plain
public class Client {
public static void main(String[] args) {
//寫封郵件
Email email = new Email("請參加會議","請與今天12:30到二會議室參加會議...");
Person person1 = new Person("張三",email);
Person person2 = person1.clone();
person2.setName("李四");
Person person3 = person1.clone();
person3.setName("王五");
person1.getEmail().setContent("請與今天12:00到二會議室參加會議...");
System.out.println(person1.getName() + "的郵件內容是:" + person1.getEmail().getContent());
System.out.println(person2.getName() + "的郵件內容是:" + person2.getEmail().getContent());
System.out.println(person3.getName() + "的郵件內容是:" + person3.getEmail().getContent());
}
}
在這里同樣是使用張三該對象實現對李四、王五拷貝,最後將張三的郵件內容改變為:請與今天12:00到二會議室參加會議...。但是結果是:
[java] view plain
張三的郵件內容是:請與今天12:00到二會議室參加會議...
李四的郵件內容是:請與今天12:00到二會議室參加會議...
王五的郵件內容是:請與今天12:00到二會議室參加會議...
這里我們就疑惑了為什麼李四和王五的郵件內容也發送了改變呢?讓他們提前30分鍾到人家會有意見的!
其實出現問題的關鍵就在於clone()方法上,我們知道該clone()方法是使用Object類的clone()方法,但是該方法存在一個缺陷,它並不會將對象的所有屬性全部拷貝過來,而是有選擇性的拷貝,基本規則如下:
1、 基本類型
如果變數是基本很類型,則拷貝其值,比如int、float等。
2、 對象
如果變數是一個實例對象,則拷貝其地址引用,也就是說此時新對象與原來對象是公用該實例變數。
3、 String字元串
若變數為String字元串,則拷貝其地址引用。但是在修改時,它會從字元串池中重新生成一個新的字元串,原有紫都城對象保持不變。
基於上面上面的規則,我們很容易發現問題的所在,他們三者公用一個對象,張三修改了該郵件內容,則李四和王五也會修改,所以才會出現上面的情況。對於這種情況我們還是可以解決的,只需要在clone()方法裡面新建一個對象,然後張三引用該對象即可:
[java] view plain
protected Person clone() {
Person person = null;
try {
person = (Person) super.clone();
person.setEmail(new Email(person.getEmail().getObject(),person.getEmail().getContent()));
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return person;
}
所以:淺拷貝只是Java提供的一種簡單的拷貝機制,不便於直接使用。
對於上面的解決方案還是存在一個問題,若我們系統中存在大量的對象是通過拷貝生成的,如果我們每一個類都寫一個clone()方法,並將還需要進行深拷貝,新建大量的對象,這個工程是非常大的,這里我們可以利用序列化來實現對象的拷貝。
二、利用序列化實現對象的拷貝
如何利用序列化來完成對象的拷貝呢?在內存中通過位元組流的拷貝是比較容易實現的。把母對象寫入到一個位元組流中,再從位元組流中將其讀出來,這樣就可以創建一個新的對象了,並且該新對象與母對象之間並不存在引用共享的問題,真正實現對象的深拷貝。
[java] view plain
public class CloneUtils {
@SuppressWarnings("unchecked")
public static <T extends Serializable> T clone(T obj){
T cloneObj = null;
try {
//寫入位元組流
ByteArrayOutputStream out = new ByteArrayOutputStream();
ObjectOutputStream obs = new ObjectOutputStream(out);
obs.writeObject(obj);
obs.close();
//分配內存,寫入原始對象,生成新對象
ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray());
ObjectInputStream ois = new ObjectInputStream(ios);
//返回生成的新對象
cloneObj = (T) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return cloneObj;
}
}
使用該工具類的對象必須要實現Serializable介面,否則是沒有辦法實現克隆的。
[html] view plain
public class Person implements Serializable{
private static final long serialVersionUID = 2631590509760908280L;
..................
//去除clone()方法
}
public class Email implements Serializable{
private static final long serialVersionUID = 1267293988171991494L;
....................
}
所以使用該工具類的對象只要實現Serializable介面就可實現對象的克隆,無須繼承Cloneable介面實現clone()方法。
㈤ 澶у︾敓紱忛煶Java甯歌佽捐℃ā寮忔葷粨
Java甯歌佽捐℃ā寮忓揩鏉ョ湅鐪
1銆佸壋寤哄瀷-宸ュ巶鏂規硶妯″紡:
(1)綆鍗曞伐鍘傛ā寮:
寤虹珛涓涓宸ュ巶綾伙紝騫跺畾涔変竴涓鎺ュ彛瀵瑰疄鐜頒簡鍚屼竴鎺ュ彛鐨勪駭鍝佺被榪涜屽壋寤恆
(2)宸ュ巶鏂規硶妯″紡:
宸ュ巶鏂規硶妯″紡鏄瀵圭畝鍗曞伐鍘傛ā寮忕殑鏀硅繘錛岀畝鍗曞伐鍘傜殑緙洪櫡鍦ㄥ共涓嶇﹀悎鈥滃紑闂鍘熷垯鈥
(3)闈欐佸伐鍘傛柟娉曟ā寮:
闈欐佸伐鍘傛ā寮忔槸灝嗗伐鍘傛柟娉曟ā寮忛噷鐨勬柟娉曠疆涓洪潤鎬佺殑錛屼笉闇瑕佸壋寤哄疄渚嬶紝鐩存帴璋冪敤鍗沖彲銆
2銆佸壋寤哄瀷-鎶借薄宸ュ巶妯″紡:
鎶借薄宸ュ巶妯″紡涓昏佺敤浜庡壋寤虹浉鍏沖硅薄鐨勫舵棌銆傚綋涓涓浜у搧鏃忎腑闇瑕佽璁捐″湪涓璧峰伐浣滄椂錛岄氳繃鎶借薄宸ュ巶妯″紡錛岃兘澶熶繚璇佸㈡埛絝濮嬬粓鍙浣跨敤鍚屼竴涓浜у搧鏃忎腑鐨勫硅薄:騫朵笖閫氳繃闅旂誨叿浣撶被鐨勭敓鎴愶紝浣垮緱瀹㈡埛絝涓嶉渶瑕佹槑紜鎸囧畾鍏蜂綋鐢熸垚綾;鎵鏈夌殑鍏蜂綋宸ュ巶閮藉疄鐜頒簡鎶借薄宸ュ巶涓瀹氫箟鐨勫叕鍏辨帴鍙o紝鍥犳ゅ彧闇瑕佹敼鍙樺叿浣撳伐鍘傜殑瀹炰緥錛屽氨鍙浠ュ湪鏌愮嶇▼搴︿笂鏀瑰彉鏁翠釜杞浠剁郴緇熺殑琛屼負銆
浣嗚ユā寮忕殑緙虹偣鍦ㄤ簬娣誨姞鏂扮殑琛屼負鏃舵瘮杈冮夯鐑︼紝濡傛灉闇瑕佹坊鍔犱竴涓鏂頒駭鍝佹棌瀵硅薄鏃訛紝闇瑕佹洿鏀規帴鍙e強鍏朵笅鎵鏈夊瓙綾伙紝榪欏繀鐒朵細甯︽潵寰堝ぇ鐨勯夯鐑︺
3銆佸壋寤哄瀷-寤洪犺呮ā寮:
寤洪犺呮ā寮忓皢澶嶆潅浜у搧鐨勫壋寤烘ラゅ垎瑙e湪鍦ㄤ笉鍚岀殑鏂規硶涓浣垮緱鍒涘緩榪囩▼鏇村姞娓呮櫚錛屼粠鑰屾洿綺劇『鎺у埗澶嶆潅瀵硅薄鐨勪駭鐢熻繃紼;閫氳繃闅旂誨嶆潅瀵硅薄鐨勬瀯寤轟笌浣跨敤錛屼篃灝辨槸灝嗕駭鍝佺殑鍒涘緩涓庝駭鍝佹湰韜鍒嗙誨紑鏉ワ紝浣垮緱鍚屾牱鐨勬瀯寤鴻繃紼嬪彲浠ュ壋寤轟笉鍚岀殑瀵硅薄;騫朵笖姣忎釜鍏蜂綋寤洪犺呴兘鐩鎬簰鐙絝嬶紝鍥犳ゅ彲浠ュ緢鏂逛究鍦版浛鎹㈠叿浣撳緩閫犺呮垨澧炲姞鏂扮殑鍏蜂綋寤洪犺咃紝鐢ㄦ埛浣跨敤涓嶅悓鐨勫叿浣撳緩閫犺呭嵆鍙寰楀埌涓嶅悓鐨勪駭鍝佸硅薄銆
4銆佸壋寤哄瀷-鍗曚緥妯″紡
鍗曚緥妯″紡鍙浠ョ『淇濈郴緇熶腑鏌愪釜綾誨彧鏈変竴涓瀹炰緥錛岃ョ被鑷琛屽疄渚嬪寲騫跺悜鏁翠釜緋葷粺鎻愪緵榪欎釜瀹炰緥鐨勫叕鍏辮塊棶鐐癸紝闄や簡璇ュ叕鍏辮塊棶鐐癸紝涓嶈兘閫氳繃鍏朵粬閫斿緞璁塊棶璇ュ疄渚嬨傚崟渚嬫ā寮忕殑浼樼偣鍦ㄤ簬:緋葷粺涓鍙瀛樺湪涓涓鍏辯敤鐨勫疄渚嬪硅薄錛屾棤闇棰戠箒鍒涘緩鍜岄攢姣佸硅薄錛岃妭綰︿簡緋葷粺璧勬簮錛屾彁楂樼郴緇熺殑鎬ц兘鍙浠ヤ弗鏍兼帶鍒跺㈡埛鎬庝箞鏍蜂互鍙婁綍鏃惰塊棶鍗曚緥瀵硅薄銆傚崟渚嬫ā寮忕殑鍐欐硶鏈夊ソ鍑犵嶏紝涓昏佹湁涓夌:鎳掓眽寮忓崟渚嬨侀タ奼夊紡鍗曚緥銆佺櫥璁板紡鍗曚緥銆
5銆佸壋寤哄瀷-鍘熷瀷妯″紡:
鍦 Java 涓錛屽師鍨嬫ā寮忕殑鏍稿績鏄灝辨槸鍘熷瀷綾 Prototype,Prototype綾婚渶瑕佸叿澶囦互涓嬩袱涓鏉′歡:瀹炵幇 Cloneable 鎺ュ彛:
閲嶅啓 Object 綾諱腑鐨 clone() 鏂規硶錛岀敤浜庤繑鍥炲硅薄鐨勬嫹璐;Object 綾諱腑鐨 clone() 鏂規硶榛樿ゆ槸嫻呮嫹璐濓紝濡傛灉鎯寵佹繁鎷瘋礉瀵硅薄錛屽垯闇瑕佸湪 clone() 鏂規硶涓鑷瀹氫箟鑷宸辯殑澶嶅埗閫昏緫銆傛祬澶嶅埗:灝嗕竴涓瀵硅薄澶嶅埗鍚庯紝鍩烘湰鏁版嵁綾誨瀷鐨勫彉閲忎細閲嶆柊鍒涘緩錛岃屽紩鐢ㄧ被鍨嬫寚鍚戠殑榪樻槸鍘熷硅薄鎵鎸囧悜鐨勫唴瀛樺湴鍧銆傛繁澶嶅埗:灝嗕竴涓瀵硅薄澶嶅埗鍚庯紝涓嶈烘槸鍩烘湰鏁版嵁綾誨瀷榪樻湁寮曠敤綾誨瀷錛岄兘鏄閲嶆柊鍒涘緩鐨勩
浣跨敤鍘熷瀷妯″紡榪涜屽壋寤哄硅薄涓嶄粎綆鍖栧硅薄鐨勫壋寤烘ラわ紝榪樻瘮new 鏂瑰紡鍒涘緩瀵硅薄鐨勬ц兘瑕佸ソ鐨勫氾紝鍥犱負 Object 綾葷殑clone() 鏂規硶鏄涓涓鏈鍦版柟娉曪紝鐩存帴鎿嶄綔鍐呭瓨涓鐨勪簩榪涘埗嫻佺壒鍒鏄澶嶅埗澶у硅薄鏃訛紝鎬ц兘鐨勫樊鍒闈炲父鏄庢樉
6.緇撴瀯鍨-閫傞厤鍣ㄦā寮
閫傞厤鍣ㄦā寮忎富瑕佺敤浜庡皢涓涓綾繪垨鑰呮帴鍙h漿鍖栨垚瀹㈡埛絝甯屾湜鐨勬牸寮忥紝浣垮緱鍘熸湰涓嶅吋瀹圭殑綾誨彲浠ュ湪涓璧峰伐浣滐紝灝嗙洰鏍囩被鍜岄傞厤鑰呯被瑙h;鍚屾椂涔熺﹀悎鈥滃紑闂鍘熷垯鈥濓紝鍙浠ュ湪涓嶄慨鏀瑰師浠g爜鐨勫熀紜涓婂炲姞鏂扮殑閫傞厤鍣ㄧ被;灝嗗叿浣撶殑瀹炵幇灝佽呭湪閫傞厤鑰呯被涓錛屽逛簬瀹㈡埛絝綾繪潵璇存槸閫忔槑鐨勶紝鑰屼笖鎻愰珮浜嗛傞厤鑰呯殑澶嶇敤鎬э紝浣嗘槸緙虹偣鍦ㄤ簬鏇存崲閫傞厤鍣ㄧ殑瀹炵幇榪囩▼姣旇緝澶嶆潅銆
鎵浠ワ紝閫傞厤鍣ㄦā寮忔瘮杈冮傚悎浠ヤ笅鍦烘櫙:
(1)緋葷粺闇瑕佷嬌鐢ㄧ幇鏈夌殑綾伙紝鑰岃繖浜涚被鐨勬帴鍙d笉絎﹀悎緋葷粺鐨勬帴
(2)浣跨敤絎涓夋柟緇勪歡錛岀粍浠舵帴鍙e畾涔夊拰鑷宸卞畾涔夌殑涓嶅悓錛屼笉甯屾湜淇鏀硅嚜宸辯殑鎺ュ彛錛屼絾鏄瑕佷嬌鐢ㄧ涓夋柟緇勪歡鎺ュ彛鐨勫姛鑳姐
7銆佺粨鏋勫瀷-瑁呴グ鍣ㄦā寮:
瑁呴グ鍣ㄦā寮忓彲浠ュ姩鎬佺粰瀵硅薄娣誨姞涓浜涢濆栫殑鑱岃矗浠庤屽疄鐜板姛鑳界殑鎷撳睍錛屽湪榪愯屾椂閫夋嫨涓嶅悓鐨勮呴グ鍣錛屼粠鑰屽疄鐜頒笉鍚岀殑琛屼負;姣斾嬌鐢ㄧ戶鎵挎洿鍔犵伒媧伙紝閫氳繃瀵逛笉鍚岀殑瑁呴グ綾昏繘琛屾帓鍒楃粍鍚堬紝鍒涢犲嚭寰堝氫笉鍚岃屼負錛屽緱鍒板姛鑳芥洿涓哄己澶х殑瀵硅薄;絎﹀悎鈥滃紑闂鍘熷垯鈥濓紝琚瑁呴グ綾諱笌瑁呴グ綾葷嫭絝嬪彉鍖栵紝鐢ㄦ埛鍙浠ユ牴鎹闇瑕佸炲姞鏂扮殑瑁呴グ綾誨拰琚瑁呴グ綾伙紝鍦ㄤ嬌鐢ㄦ椂鍐嶅瑰叾榪涜岀粍鍚堬紝鍘熸湁浠g爜鏃犻』鏀瑰彉銆
浣嗘槸瑁呴グ鍣ㄦā寮忎篃瀛樺湪緙虹偣錛岄栧厛浼氫駭鐢熷緢澶氱殑灝忓硅薄澧炲姞浜嗙郴緇熺殑澶嶆潅鎬э紝絎浜屾槸鎺掗敊姣旇緝鍥伴毦錛屽逛簬澶氭¤呴グ鐨勫硅薄錛岃皟璇曟椂瀵繪壘閿欒鍙鑳介渶瑕侀愮駭鎺掓煡錛岃緝涓虹儲鐞愩
8銆佺粨鏋勫瀷-浠g悊妯″紡:
浠g悊妯″紡鐨勮捐″姩鏈烘槸閫氳繃浠g悊瀵硅薄鏉ヨ塊棶鐪熷疄瀵硅薄錛岄氳繃寤虹珛涓涓瀵硅薄浠g悊綾伙紝鐢變唬鐞嗗硅薄鎺у埗鍘熷硅薄鐨勫紩鐢錛屼粠鑰屽疄鐜板圭湡瀹炲硅薄鐨勬搷浣溿傚湪浠g悊妯″紡涓錛屼唬鐞嗗硅薄涓昏佽搗鍒頒竴涓涓浠嬬殑浣滅敤錛岀敤浜庡崗璋冧笌榪炴帴璋冪敤鑰(鍗沖㈡埛絝)鍜岃璋冪敤鑰(鍗崇洰鏍囧硅薄)錛屽湪涓瀹氱▼搴︿笂闄嶄綆浜嗙郴緇熺殑鑰﹀悎搴︼紝鍚屾椂涔熶繚鎶や簡鐩鏍囧硅薄銆備絾緙虹偣鏄鍦ㄨ皟鐢ㄨ呬笌琚璋冪敤鑰呬箣闂村炲姞浜嗕唬鐞嗗硅薄錛屽彲鑳戒細閫犳垚璇鋒眰鐨勫勭悊閫熷害鍙樻參銆
9銆佺粨鏋勫瀷-妗ユ帴妯″紡:
妗ユ帴妯″紡灝嗙郴緇熺殑鎶借薄閮ㄥ垎涓庡疄鐜伴儴鍒嗗垎紱昏В鑰︼紝浣誇粬浠鍙浠ョ嫭絝嬬殑鍙樺寲銆備負浜嗚揪鍒拌╂娊璞¢儴鍒嗗拰瀹炵幇閮ㄥ垎鐙絝嬪彉鍖栫殑鐩鐨勶紝妗ユ帴妯″紡浣跨敤緇勫悎鍏崇郴鏉ヤ唬鏇跨戶鎵垮叧緋伙紝鎶借薄閮ㄥ垎鎷ユ湁瀹炵幇閮ㄥ垎鐨勬帴鍙e硅薄錛屼粠鑰岃兘澶熼氳繃榪欎釜鎺ュ彛瀵硅薄鏉ヨ皟鐢ㄥ叿浣撳疄鐜伴儴鍒嗙殑鍔熻兘銆備篃灝辨槸璇達紝妗ユ帴妯″紡涓鐨勬ˉ鎺ユ槸涓涓鍗曟柟鍚戠殑鍏崇郴錛屽彧鑳藉熸娊璞¢儴鍒嗗幓浣跨敤濂栫幇閮ㄥ垎鐨勫硅薄錛岃屼笉鑳藉弽榪囨潵銆
妗ユ帴妯″紡絎﹀悎鈥滃紑闂鍘熷垯鈥濓紝鎻愰珮浜嗙郴緇熺殑鍙鎷撳睍鎬э紝鍦ㄤ袱涓鍙樺寲緇村害涓浠繪剰鎵╁睍涓涓緇村害錛岄兘涓嶉渶瑕佷慨鏀瑰師鏉ョ殑緋葷粺:騫朵笖瀹炵幇緇嗚妭瀵瑰㈡埛涓嶉忔槑錛屽彲浠ラ殣鈃忓疄鐜扮粏鑺傘備絾鏄鐢變簬鑱氬悎鍏崇郴寤虹珛鍦ㄦ娊璞″眰錛岃佹眰寮鍙戣呴拡瀵規娊璞¤繘琛岀紪紼嬶紝榪欏炲姞緋葷粺鐨勭悊瑙e拰璁捐¢毦搴︺
10銆佺粨鏋勫瀷-澶栬傛ā寮:
瑙傛ā寮忛氳繃瀵瑰㈡埛絝鎻愪緵涓涓緇熶竴鐨勬帴鍙o紝鐢ㄤ簬璁塊棶瀛愮郴緇熶腑鐨勪竴緹ゆ帴鍙c備嬌鐢ㄥ栬傛ā寮忔湁浠ヤ笅鍑犵偣濂藉:
(1)鏇村姞鏄撶敤:浣垮緱瀛愮郴緇熸洿鍔犳槗鐢錛屽㈡埛絝涓嶅啀闇瑕佷簡瑙e瓙緋葷粺鍐呴儴鐨勫疄鐜幫紝涔熶笉闇瑕佽窡浼楀氬瓙緋葷粺鍐呴儴鐨勬ā鍧楄繘琛屼氦浜掞紝鍙闇瑕佽窡澶栬傜被浜や簰灝卞彲浠ヤ簡;
(2)鏉炬暎鑰﹀悎:灝嗗㈡埛絝涓庡瓙緋葷粺瑙h︼紝璁╁瓙緋葷粺鍐呴儴鐨勬ā鍧楄兘鏇村規槗鎵╁睍鍜岀淮鎶ゃ
(3)鏇村ソ鐨勫垝鍒嗚塊棶灞傛: 閫氳繃鍚堢悊浣跨敤 Facade錛屽彲浠ユ洿濂藉湴鍒掑垎璁塊棶鐨勫眰嬈★紝鏈変簺鏂規硶鏄瀵圭郴緇熷栫殑錛屾湁浜涙柟娉曟槸緋葷粺鍐呴儴浣跨敤鐨勩傛妸闇瑕佹毚闇茬粰澶栭儴鐨勫姛鑳介泦涓鍒伴棬闈涓錛岃繖鏍鋒棦鏂逛究瀹㈡埛絝浣跨敤錛屼篃寰堝ソ鍦伴殣鈃忎簡鍐呴儴鐨勭粏鑺傘
11銆佺粨鏋勫瀷-緇勫悎妯″紡:
緇勫悎妯″紡灝嗗彾瀛愬硅薄鍜屽瑰櫒瀵硅薄榪涜岄掑綊緇勫悎錛屽艦鎴愭爲褰㈢粨鏋勪互琛ㄧず鈥滈儴鍒-鏁翠綋鈥濈殑灞傛$粨鏋勶紝浣垮緱鐢ㄦ埛瀵瑰崟涓瀵硅薄鍜岀粍鍚堝硅薄鐨勪嬌鐢ㄥ叿鏈変竴鑷存э紝鑳藉熷儚澶勭悊鍙跺瓙瀵硅薄涓鏍鋒潵澶勭悊緇勫悎瀵硅薄錛屾棤闇榪涜屽尯鍒嗭紝浠庤屼嬌鐢ㄦ埛紼嬪簭鑳藉熶笌澶嶆潅鍏冪礌鐨勫唴閮ㄧ粨鏋勮繘琛岃В鑰︺
緇勫悎妯″紡鏈鍏抽敭鐨勫湴鏂規槸鍙跺瓙瀵硅薄鍜岀粍鍚堝硅薄瀹炵幇浜嗙浉鍚岀殑鎶借薄鏋勫緩綾伙紝瀹冩棦鍙琛ㄧず鍙跺瓙瀵硅薄錛屼篃鍙琛ㄧず瀹瑰櫒瀵硅薄錛屽㈡埛浠呬粎闇瑕侀拡瀵硅繖涓鎶借薄鏋勫緩綾昏繘琛岀紪紼嬶紝榪欏氨鏄緇勫悎妯″紡鑳藉熷皢鍙跺瓙鑺傜偣鍜屽硅薄鑺傜偣榪涜屼竴鑷村勭悊鐨勫師鍥犮
12銆佺粨鏋勫瀷-浜鍏冩ā寮:
浜鍏冩ā寮忛氳繃鍏變韓鎶鏈鏈夋晥鍦版敮鎸佺粏綺掑害銆佺姸鎬佸彉鍖栧皬鐨勫硅薄澶嶇敤錛屽綋緋葷粺涓瀛樺湪鏈夊氫釜鐩稿悓鐨勫硅薄錛岄偅涔堝彧鍏變韓涓浠戒笉蹇呮瘡涓閮藉幓瀹炰緥鍖栦竴涓瀵硅薄錛屾瀬澶у湴鍑忓皯緋葷粺涓瀵硅薄鐨勬暟閲忥紝浠庤岃妭鐪佽祫婧愩
浜鍏冩ā寮忕殑鏍稿績鏄浜鍏冨伐鍘傜被錛屼韓鍏冨伐鍘傜被緇存姢浜嗕竴涓瀵硅薄瀛樺偍奼狅紝褰撳㈡埛絝闇瑕佸硅薄鏃訛紝棣栧厛浠庝韓鍏冩睜涓鑾峰彇錛屽傛灉浜鍏冩睜涓瀛樺湪瀵硅薄瀹炰緥鍒欑洿鎺ヨ繑鍥烇紝濡傛灉浜鍏冩睜涓涓嶅瓨鍦錛屽垯鍒涘緩涓涓鏂扮殑浜鍏冨硅薄瀹炰緥榪斿洖緇欑敤鎴鳳紝騫跺湪浜鍏冩睜涓淇濆瓨璇ユ柊澧炲硅薄錛岃繖鐐規湁浜涘崟渚嬬殑鎰忔濄
宸ュ巶綾婚氬父浼氫嬌鐢ㄩ泦鍚堢被鍨嬫潵淇濆瓨瀵硅薄錛屽 HashMap銆丠ashtable銆乂ector 絳夌瓑錛屽湪 Java 涓錛屾暟鎹搴撹繛鎺ユ睜銆佺嚎紼嬫睜絳夐兘鏄鐢ㄤ韓鍏冩ā寮忕殑搴旂敤銆
㈥ java如何深度一個object
方法一:把對象序列化之後再反序列化,之後得到的對象就是深度克隆的對象;
方法二:自己重寫方法,不過有點麻煩。
㈦ java深拷貝對象與新建對象哪個更耗資源
這個問題沒有可比性:
首先淺克隆比new性能高
而深克隆包括克隆對象本身以及對象內部的所有成員, 以及成員的成員等,
如果這個對象有一個集合欄位, 這個欄位里有100w個對象, 那麼深克隆要克隆100w+1個對象, 而你所說的新建對象, 如果是new一個對象, 然後set這個100w的集合, 那麼肯定性能更好, 而你如果是new一個對象, 然後new一個集合, 然後把集合里的100w個對象每個都重新new, 並添加到集合中, 然後賦值到新的對象上, 那麼還是克隆的性能好
㈧ java.util.ArrayList.clone是不是徹底的克隆
你好,官方api 說明如下:
Returns a shallow of this ArrayList instance. (The elements themselves are not copied.)
arraylist.clone是淺拷貝,淺拷貝是指拷貝對象時僅僅拷貝對象本身(包括對象中的基本變數),而不拷貝對象包含的引用指向的對象。深拷貝不僅拷貝對象本身,而且拷貝對象包含的引用指向的所有對象。