java深克隆
㈠ java中的克隆技術具體有什麼應用
Clone基本知識儲備
在Java里提到clone技術,就不能不提java.lang.Cloneable介面和含有clone方法的Object類。所有具有clone功能的類都有一個特性,那就是它直接或間接地實現了Cloneable介面。否則,我們在嘗試調用clone()方法時,將會觸發CloneNotSupportedException異常。 下面我們通過對Object類的部分源碼的分析,來發現和理解這一特性。
l clone的實現
1.實現Cloneable介面
通過上一篇的介紹,我們知道,一個類若要具備clone功能,就必須實現Cloneable介面。做到這一步,clone功能已經基本實現了。Clone功能對我們來說,最主要的還是要能夠使用它。那麼我們如何才能使用clone功能呢?答案是覆蓋Object#clone()方法。
2. 覆蓋Object#clone()方法
為什麼需要覆蓋Object#clone()方法?這里得再次從jdk源碼說起。JDK中Object# clone()方法的原型是:
protected native Object clone() throws CloneNotSupportedException;
是否注意到,這里clone()方法修飾符是protected,而不是public。這種訪問的不可見性使得我們對Object#clone()方法不可見。相信讀者已明白為什麼要覆蓋Object#clone()方法。而且,覆蓋的方法的修飾符必須是public,如果還保留為protected,覆蓋將變得沒有實際意義。下面舉一個具有clone功能的簡單的例子:
/*
* 具有clone功能的類的例子
*/
public class CloneableObjExample implements Cloneable {
//……部分代碼已省略……
private String name = null;
private int score = 0;
/**
* NOTE: 將protected 修飾符 更改為 public
* @see java.lang.Object#clone()
*/
public/*protected*/ Object clone() throws CloneNotSupportedException {
// call父類的clone方法
Object result = super.clone();
//TODO: 定製clone數據
return result;
}
}
3.定製clone
至此,clone已經真相大白。Clone的對象我們可以對其進行定製。還就上面的例子來說。下面的方法對功能做了一定的增強:
public/*protected*/ Object clone() throws CloneNotSupportedException {
// call父類的clone方法
CloneableObjExample result = (CloneableObjExample)super.clone();
//TODO: 定製clone數據
//雖然」clone」了,但還可以做點調整
result.name = 「New Name」;
result.score = 90;
return result;
}
本篇介紹了如何實現clone。接下來的篇幅將就縱深clone等clone的高級特性進行分析。
本章將進入clone的高級特性,著重講述縱深clone技術。
Clone通常有兩種類型即淺clone和深clone。首先,分析一下兩種的不同。淺clone和深clone都是clone,它們本質區別是對象內部的成員屬性(非原生類型屬性,如int等)在clone時是否處理為引用。如果仍然保留為引用,則稱為淺clone,反之稱為深clone。其實這兩個概念也是相對的概念。在處理上它們有點區別,淺clone方式得到clone對象即可,深clone方式在得到clone對象後,還需要對引用的成員屬性進行「clone」處理。從這個層次上說,深clone並沒有什麼特別地困難,簡單講就是創建好對象,再設置一些成員屬性。關於深clone,網上的文章已經有太多,有點目不暇接的感覺,本文不再贅述,這也不是本文的重點。
本文的重點是要闡述縱深clone,亦即「N深clone」。深到什麼程度為止?本文描述的目標是一直深到你想要的程度,包括深到不能再深的程度。
㈡ java怎麼樣構造函數復制一個對象
一、用Object 本身的復制對象的方法, clone()。對象可克隆的類必須實現Cloneable介面,並且clone方法是淺克隆。
二、類實現Serializable,用ObjectOutputStream、ObjectInputStream 來復制對象。
對象克隆有點復雜,尤其是第一種。
關於這個問題你可以搜索:
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關鍵字將其排除在復制過程中。
㈣ java.util.ArrayList.clone是不是徹底的克隆
你好,官方api 說明如下:
Returns a shallow of this ArrayList instance. (The elements themselves are not copied.)
arraylist.clone是淺拷貝,淺拷貝是指拷貝對象時僅僅拷貝對象本身(包括對象中的基本變數),而不拷貝對象包含的引用指向的對象。深拷貝不僅拷貝對象本身,而且拷貝對象包含的引用指向的所有對象。
㈤ java中的淺克隆和深克隆是什麼
淺克隆:僅僅復制所克隆的對象,而不復制它所引用的對象。
被復制對象的所有變數都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。
深克隆:把要復制的對象所引用的對象都復制了一遍。
那些引用其他對象的變數將指向被復制過的新對象,而不再是原有的那些被引用的對象。
很明顯二者時間消耗有差距,在不影響的情況下盡量用淺克隆
注意區分與C語言的淺克隆深克隆 那個是引用地址與重新分配地址構建的區別,詳細可以參見:
http://www.cnblogs.com/yxnchinahlj/archive/2010/09/20/1831615.html
㈥ java深拷貝對象與新建對象哪個更耗資源
這個問題沒有可比性:
首先淺克隆比new性能高
而深克隆包括克隆對象本身以及對象內部的所有成員, 以及成員的成員等,
如果這個對象有一個集合欄位, 這個欄位里有100w個對象, 那麼深克隆要克隆100w+1個對象, 而你所說的新建對象, 如果是new一個對象, 然後set這個100w的集合, 那麼肯定性能更好, 而你如果是new一個對象, 然後new一個集合, 然後把集合里的100w個對象每個都重新new, 並添加到集合中, 然後賦值到新的對象上, 那麼還是克隆的性能好
㈦ java如何實現將一個記事本文件內容復制到另一個文件
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class CopyMove {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
CopyMove cm = new CopyMove();
cm.("h:\\1.txt", "c:\\2.txt");
cm.move("h:\\3.txt", "h:\\r\\e\\4.txt");
}
//文件復制前必須得到當前文件夾名字且要有\
//當復制深層次路徑時要用mkdirs方法
public void (String path1,String path2){
try {
FileInputStream fis = new FileInputStream(path1);
int l = fis.available();
byte[] c = new byte[l];
fis.read(c);
fis.close();
int i = path2.lastIndexOf("\\")+1;
System.out.println(i);
String path = path2.substring(0, i);
System.out.println(path);
File f = new File(path);
f.mkdirs();
// System.out.println(f.getAbsolutePath());
// System.out.println(f.isDirectory());
FileOutputStream fos = new FileOutputStream(path2);
fos.write(c);
fos.close();
System.out.println("文件復製成功");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("文件復制失敗");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void move(String path1,String path2){
try {
FileInputStream fis = new FileInputStream(path1);
int l = fis.available();
byte[] c = new byte[l];
fis.read(c);
fis.close();
int i = path2.lastIndexOf("\\");
//System.out.println(i);
String path = path2.substring(0, i);
System.out.println(path);
File f = new File(path);
f.mkdirs();
// System.out.println(f.getAbsolutePath());
// System.out.println(f.isDirectory());
FileOutputStream fos = new FileOutputStream(path2);
fos.write(c);
fos.close();
System.out.println("文件移動成功");
File f2 = new File(path1);
f2.delete();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
System.out.println("文件移動失敗");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
㈧ 誰能給出一個java中深拷貝 的例子 啊,我不知道是啥東西,最好能解釋下深拷貝含義.
舉個最簡單的例子:
class A {
public int i;
public int j;
}
A a = new A();
淺拷貝:
A a1 = a;
深拷貝:
A a1 = new A();
a1.i = a.i;
a1.j = a.j;
感覺如下:
淺拷貝只拷貝對象本身
深拷貝則拷貝對象中引用的對象,一直拷貝下去。
㈨ java如何深度一個object
方法一:把對象序列化之後再反序列化,之後得到的對象就是深度克隆的對象;
方法二:自己重寫方法,不過有點麻煩。
㈩ java里clone方法的問題
首先必須實現介面,
public interface Cloneable此類實現了 Cloneable 介面,以指示 Object.clone() 方法可以合法地對該類實例進行按欄位復制。
如果在沒有實現 Cloneable 介面的實例上調用 Object 的 clone 方法,則會導致拋出 CloneNotSupportedException 異常。
按照慣例,實現此介面的類應該使用公共方法重寫 Object.clone(它是受保護的)。請參閱 Object.clone(),以獲得有關重寫此方法的詳細信息。
==》protected Object clone() throws CloneNotSupportedException
注意,此介面不 包含 clone 方法。因此,因為某個對象實現了此介面就克隆它是不可能的。即使 clone 方法是反射性調用的,也無法保證它將獲得成功。
public class Box implements Cloneable{
public Date d = new Date();
@Override
public Box clone() throws CloneNotSupportedException
{
Box cloned = (Box)super.clone();
cloned.d = (Date)d.clone();
return (Box)super.clone();
}
public static void main(String[] args) throws Exception {
Box b = new Box();
Box b2 = (Box)b.clone();
System.out.println(b.d == b2.d);
}
}
測試後直接返回的話結果是地址相等。
你在克隆後用了set方法重新操作了,肯定是不一樣的。。。。!!!
3,注釋起來後結果是改變了的,你會不會是沒編譯保存。
你們老師是說的對的
你好,當然知道 你說的那樣。我正是因為三個的試過了,所以最後沒改回去,那不正是你第二個問題嘛。。。
如果是深克隆就是FALSE 不是深克隆就返回TRUE啊。