java对象拷贝常见面试题及应答汇总
为什么要使用克隆?
想对一个对象进行处理,又想保留原有的数据进行接下来的操作,就需要克隆了,Java语言中克隆针对的是类的实例。
如何实现对象克隆?
有两种方式:
实现Cloneable接口并重写Object类中的clone()方法;实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆,代码如下:
importjava.io.ByteArrayInputStream;
importjava.io.ByteArrayOutputStream;
importjava.io.ObjectInputStream;
importjava.io.ObjectOutputStream;
importjava.io.Serializable;
publicclassMyUtil{
privateMyUtil(){
thrownewAssertionError();
}
@SuppressWarnings("unchecked")
publicstaticTclone(Tobj)throwsException{
ByteArrayOutputStreambout=newByteArrayOutputStream();
ObjectOutputStreamoos=newObjectOutputStream(bout);
oos.writeObject(obj);
ByteArrayInputStreambin=newByteArrayInputStream(bout.toByteArray());
ObjectInputStreamois=newObjectInputStream(bin);
return(T)ois.readObject();
//说明:调用ByteArrayInputStream或ByteArrayOutputStream对象的close方法没有任何意义
//这两个基于内存的流只要垃圾回收器清理对象就能够释放资源,这一点不同于对外部资源(如文件流)的释放
}
}
下面是测试代码:
importjava.io.Serializable;
/**
*人类
*@authornnngu
*
*/
classPersonimplementsSerializable{
privatestaticfinallongserialVersionUID=-9102017020286042305L;
privateStringname;//姓名
privateintage;//年龄
privateCarcar;//座驾
publicPerson(Stringname,intage,Carcar){
this.name=name;
this.age=age;
this.car=car;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicintgetAge(){
returnage;
}
publicvoidsetAge(intage){
this.age=age;
}
publicCargetCar(){
returncar;
}
publicvoidsetCar(Carcar){
this.car=car;
}
@Override
publicStringtoString(){
return"Person[name="+name+",age="+age+",car="+car+"]";
}
}
/**
*小汽车类
*@authornnngu
*
*/
classCarimplementsSerializable{
privatestaticfinallongserialVersionUID=-5713945027627603702L;
privateStringbrand;//品牌
privateintmaxSpeed;//最高时速
publicCar(Stringbrand,intmaxSpeed){
this.brand=brand;
this.maxSpeed=maxSpeed;
}
publicStringgetBrand(){
returnbrand;
}
publicvoidsetBrand(Stringbrand){
this.brand=brand;
}
publicintgetMaxSpeed(){
returnmaxSpeed;
}
publicvoidsetMaxSpeed(intmaxSpeed){
this.maxSpeed=maxSpeed;
}
@Override
publicStringtoString(){
return"Car[brand="+brand+",maxSpeed="+maxSpeed+"]";
}
}
classCloneTest{
publicstaticvoidmain(String[]args){
try{
Personp1=newPerson("郭靖",33,newCar("Benz",300));
Personp2=MyUtil.clone(p1);//深度克隆
p2.getCar().setBrand("BYD");
//修改克隆的Person对象p2关联的汽车对象的品牌属性
//原来的Person对象p1关联的汽车不会受到任何影响
//因为在克隆Person对象时其关联的汽车对象也被克隆了
System.out.println(p1);
}catch(Exceptione){
e.printStackTrace();
}
}
}
注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是好过把问题留到运行时。
深拷贝和浅拷贝区别是什么?
浅拷贝只是复制了对象的引用地址,两个对象指向同一个内存地址,所以修改其中任意的值,另一个值都会随之变化,这就是浅拷贝(例:assign())深拷贝是将对象及值复制过来,两个对象修改其中任意的值另一个值不会改变,这就是深拷贝(例:JSON.parse()和JSON.stringify(),但是此方法无法复制函数类型)
到此这篇关于java对象拷贝常见面试题及应答汇总的文章就介绍到这了,更多相关java对象拷贝常见面试题内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。