java cloneable 用途_java中cloneable的使用「建议收藏」

java cloneable 用途_java中cloneable的使用「建议收藏」什么是java中的浅克隆和深克隆?浅克隆:克隆对象中的变量与之前对象的值相同,并且对象中的引用类型变量仍然指向原来对象引用类型变量的地址.深克隆:克隆对象中的变量与之前对象的值相同,并且对象中的引用类型变量指向了新的对象的引用变量的地址.要想实现克隆,只需定义的类声明下cloneable这个标记性接口,并且衍生重写Object类中就有的clone()方法即可.为什么类要首先声明cloneable标…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

什么是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”));

}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/181903.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Winform技巧:TreeView导入Excel

    Winform技巧:TreeView导入Excel

  • Cutout Standard扣图软件「建议收藏」

    Cutout Standard扣图软件「建议收藏」CutoutStandard是款功能强大且专业的抠图工具。内置强大的功能,可以从相片背景中将您需要的对象抠出和制作蒙太奇图片,且提供Photoshop的抠图插件,非常方便实用。感兴趣的朋友快来下载使用吧。软件功能  【更改背景】CutoutStandard最新版允许您将新剪切的对象与您选择的另一个图像组合在一起。例如,您可以将剪切对象放在“其他位置”。  【模糊背景】选择此功能时,程序切换到模糊模式。您可以将图像的背景模糊到不同程度。此外,背景将被保留,并且唯一的组件会受到模糊效果的影响。这

  • 动态链接库(DLL)初始化例程失败_无法装入solidworks DLL文件

    动态链接库(DLL)初始化例程失败_无法装入solidworks DLL文件关于solidworks中的:动态链接库(DLL)初始化例失败的解决方法

    2022年10月21日
  • 工作流模块Jar包启动报错:liquibase – Waiting for changelog lock….

    工作流模块Jar包启动报错:liquibase – Waiting for changelog lock….

  • typora主题修改后保存_typora设置字体

    typora主题修改后保存_typora设置字体typora买了几天了,一直思考什么时候去学习下,毕竟,以前是免费的,没那么多讲究,就是把它当做一个普普通通的编辑器使用。似乎也没有用它的任何功能,甚至连官网文档那么详细的解释都没看;可见,虽然使用着免费的优秀的产品,竟然连最基础的功能都不会。换了个主题,这个是看着官网文档做的。主题下载首先,去下载了一个主题,https://theme.typora.io/;选一个自己喜欢的。设置主题其次,打开偏好设置,找到主题保存的文件夹。操作如下:流程图#mermaid-svg-FyDmLYlb0MV3

    2022年10月28日
  • 使用R中merge()函数合并数据[通俗易懂]

    使用R中merge()函数合并数据[通俗易懂]使用R中merge()函数合并数据在R中可以使用merge()函数去合并数据框,其强大之处在于在两个不同的数据框中标识共同的列或行。如何使用merge()获取数据集中交叉部分merge()最简单的形式为获取两个不同数据框中交叉部分。举例,获取cold.states和large.states完全匹配的数据。代码如下:>merge(cold.states,large….

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号