日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

java cloneable 用途_java中cloneable的使用

發布時間:2025/3/21 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java cloneable 用途_java中cloneable的使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是java中的淺克隆和深克隆?

淺克隆:克隆對象中的變量與之前對象的值相同,并且對象中的引用類型變量仍然指向原來對象引用類型變量的地址.

深克隆:克隆對象中的變量與之前對象的值相同,并且對象中的引用類型變量指向了新的對象的引用變量的地址.

要想實現克隆,只需定義的類聲明下cloneable這個標記性接口,并且衍生重寫Object類中就有的clone()方法即可.

為什么類要首先聲明cloneable標記接口,然后重寫clone()方法?因為不聲明cloneable調用clone()方法會拋出CloneNotSupportedException異常,源碼如下:

protected Object clone() throws CloneNotSupportedException {

if (!(this instanceof Cloneable)) {

throw new CloneNotSupportedException("Class " + getClass().getName() +

" doesn't implement Cloneable");

}

return internalClone();

}

/*

* Native helper method for cloning.

*/

private native Object internalClone();

在上一節中講了java中Serializable與Parcelable的使用序列化與反序列化的問題。事實上利用對象輸出流對對象進行序列化,利用對象的輸入流對對象進行反序列化也可以實現克隆,如果對象中依賴的其他對象的引用也實現了序列化(即引用類實現了serializable標記接口)就實現了深度克隆,否則實現了淺克隆.

實現了Serializable接口的Company

public class Company implements Serializable {//Serializable接口是空的,沒有聲明的方法及常量

private static final long serialVersionUID = 1L; //序列化標識

private String name;

private String address;

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public String getAddress() {

return address;

}

public void setAddress(String address) {

this.address = address;

}

public Company(String name, String address) {

this.name = name;

this.address = address;

}

@Override

public String toString() {

return "company name is:"+name+",address is:"+address;

}

}

獲得實現了Serializable接口的克隆實例調用方法。

private T getCopyObj(T t) {

ByteArrayOutputStream byteArrayOutputStream = null;

ObjectOutputStream objectOutputStream = null;

ByteArrayInputStream byteArrayInputStream = null;

ObjectInputStream objectInputStream = null;

try {

byteArrayOutputStream = new ByteArrayOutputStream();

objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);

objectOutputStream.writeObject(t);//序列化對象

objectOutputStream.flush();

byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());

objectInputStream = new ObjectInputStream(byteArrayInputStream);

T t1 = (T) objectInputStream.readObject();

return t1;

} catch (Exception e) {

e.printStackTrace();

} finally {

if (byteArrayOutputStream != null) {

try {

byteArrayOutputStream.close();

byteArrayOutputStream = null;

} catch (IOException e) {

e.printStackTrace();

}

}

if (objectOutputStream != null) {

try {

objectOutputStream.close();

objectOutputStream = null;

} catch (IOException e) {

e.printStackTrace();

}

}

if (byteArrayInputStream != null) {

try {

byteArrayInputStream.close();

byteArrayInputStream = null;

} catch (IOException e) {

e.printStackTrace();

}

}

if (objectInputStream != null) {

try {

objectInputStream.close();

objectInputStream = null;

} catch (IOException e) {

e.printStackTrace();

}

}

}

return null;

}

}

測試通過的testCase,說明通過Serializable的反序列化創建的是一個新的對象,不再是之前的對象了。

@Test

public void test() throws CloneNotSupportedException {

Company company=new Company("百度","上地十街");

Company copyCompany=getCopyObj(company);

copyCompany.setName("騰訊");

Assert.assertEquals(false,company==copyCompany);

Assert.assertEquals(true,company.getName().equals("百度"));

Assert.assertEquals(true,copyCompany.getName().equals("騰訊"));

}

實現了Clonable克隆的例子

public class People implements Cloneable {

private String name;

private int age;

public People(String name, int age) {

this.name = name;

this.age = age;

}

@Override

protected Object clone() throws CloneNotSupportedException {

return super.clone();

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

驗證通過的case,表明了克隆出來的對象與原來的對象地址不一樣,是一個新的對象,所以克隆對象中的name和age是新的.

@Test

public void test() throws CloneNotSupportedException {

People people = new People("storm", 30);

People clonePeople = (People) people.clone();

clonePeople.setName("stormClone");

clonePeople.setAge(29);

Assert.assertFalse(people == clonePeople);

System.out.println("people name=" + people.getName());//people name=storm

System.out.println("people age=" + people.getAge());//people age=30

System.out.println("clonePeople name=" + clonePeople.getName());//clonePeople name=stormClone

System.out.println("clonePeople age=" + clonePeople.getAge());//clonePeople age=29

}

使用cloneable實現淺克隆

public class Animal {

private String animalName;

public Animal(String animalName) {

this.animalName = animalName;

}

public String getAnimalName() {

return animalName;

}

public void setAnimalName(String animalName) {

this.animalName = animalName;

}

}

public class People implements Cloneable {

private String name;

private int age;

private Animal animal;//克隆對象中的引用型變量

public People(String name, int age,Animal animal) {

this.name = name;

this.age = age;

this.animal=animal;

}

@Override

protected Object clone() throws CloneNotSupportedException {

return super.clone();

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public Animal getAnimal() {

return animal;

}

public void setAnimal(Animal animal) {

this.animal = animal;

}

}

驗證通過的case,表明了克隆對象的引用型變量animal并未發生改變,也即使內存中的地址并未發生改變,所以對其name的更改會影響原對象與克隆對象的值.

@Test

public void test() throws CloneNotSupportedException {

Animal animal=new Animal("cat");

People people = new People("storm", 30,animal);

People clonePeople = (People) people.clone();

animal.setAnimalName("dog");

Assert.assertFalse(people == clonePeople);

Assert.assertTrue(people.getAnimal()==clonePeople.getAnimal());

Assert.assertTrue(people.getAnimal().getAnimalName().equals("dog"));

Assert.assertTrue(clonePeople.getAnimal().getAnimalName().equals("dog"));

}

使用cloneable實現深克隆(實現很簡單只需要引用類型變量實現cloneable接口即可),相比淺克隆,只需做如下修改.

public class Animal implements Cloneable{

private String animalName;

public Animal(String animalName) {

this.animalName = animalName;

}

public String getAnimalName() {

return animalName;

}

public void setAnimalName(String animalName) {

this.animalName = animalName;

}

@Override

protected Object clone() throws CloneNotSupportedException {

return super.clone();

}

}

驗證通過的case,表明了克隆對象的引用型變量animal發生改變,也即內存中的地址發生改變,所以對其name的更改不會影響克隆對象的值.同時說明了進行深克隆會把所有的引用類型都實現cloneable接口,如果克隆對象中的引用類型變量比較多的話,這牽涉的工作量就會比較大了,這時我們考慮使用上面實現Serializable實現克隆的方式,缺點是反復進行IO操作,內存開銷大.

@Test

public void test() throws CloneNotSupportedException {

Animal animal=new Animal("cat");

People people = new People("storm", 30,animal);

People clonePeople = (People) people.clone();

Animal cloneAnimal=(Animal) animal.clone();

clonePeople.setAnimal(cloneAnimal);

animal.setAnimalName("dog");

Assert.assertFalse(people == clonePeople);

Assert.assertFalse(people.getAnimal()==clonePeople.getAnimal());

Assert.assertTrue(people.getAnimal().getAnimalName().equals("dog"));

Assert.assertTrue(clonePeople.getAnimal().getAnimalName().equals("cat"));

}

總結

以上是生活随笔為你收集整理的java cloneable 用途_java中cloneable的使用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。