Java之拷贝
作者:互联网
定义
- 通过原型实例指定创建对象的类型,并通过对象的拷贝原型,来实现对象的创建。它是一种创建型设计模式,能够复制已有对象,而代码不会过度依赖他所属的类
原理
- 将一个原型实例对象传递给药发送创建的对象,要发送创建的对象通过请求原型实例对象拷贝来实现对象的创建
使用场景
- 1.需要复制一些对象,同时又希望代码独立于这些对象所属的具体类
- 2.当创建给定类型的实例过程很复杂时
作用
- 更简单的获取相同或相似的对象实例,在java中就是拷贝,克隆
优点
- 简化了对象的创建
- 对于创建对象,和new 对象相比在性能要好的对,因为clone是一个本地方法,直接操作内存中的二进制流
Java中实现拷贝的条件
- 1.需要实现Cloneable接口,用于通知虚拟机可以安全的实现此类接口类的clone方法,若没有实现该接口,调用clone()方法将抛CloneNotSuppoertException
- 2.重写clone()方法,该方法是object中的一个方法,用于返回一个对象的拷贝
拷贝的分类
-
浅拷贝
克隆出来的对象实例一摸一样,对象的属性如果是引用数据类型,那么指向同一地址值,无论是修改原来的对象,还是修改克隆出来的对象,只要引用数据类型修改了,那么两个对象同时被修改了,因为他们共享同一地址值;对于基本数据类型,当某个对象的数据发生改变时,不影响林外一个对象
-
深拷贝
克隆出来的对象实例一模一样,但引用属性被克隆 ,两个对象中的引用对象没有任何关联,无论那个对象的;对于基本数据类型,当某个对象的数据发生改变时,不影响林外一个对象
实例之深复制
static class Sheep implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private Integer age;
private String color;
private Sheep friend;
public Sheep getFriend() {
return friend;
}
public void setFriend(Sheep friend) {
this.friend = friend;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
/**
* 深复制 采用流的方式写入和读取
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public Object deepClone() throws IOException,ClassNotFoundException{
//通过输出流进行数据的写入
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(this);
//通过输入流进行读取
ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
Object obj = ois.readObject();
bos.flush();
bos.close();
oos.close();
bis.close();
ois.close();
return obj;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
", friend=" + friend +
'}';
}
}
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
Sheep s=new Sheep();
s.setName("ss");
s.friend=new Sheep();
s.friend.setName("喜洋洋");
Sheep s1= (Sheep) s.deepClone();
s.setName("原数据修改name");
s.friend.setName("你是谁");
System.out.println("原对象:"+s+" 复制对象:"+s1);
System.out.println("原对象:"+s.toString()+" 复制对象:"+s1.toString());
}
//打印信息
原对象: Sheep{name='原数据修改name', age=null, color='null', friend=Sheep{name='你是谁', age=null, color='null', friend=null}}
复制对象:Sheep{name='复制对象修改数据', age=null, color='null', friend=Sheep{name='喜洋洋', age=null, color='null', friend=null}}
- 1.深拷贝需要实现Serializable接口,使属性序列化,然后通过IO进行读写。
- 2.在深拷贝中无论是基本数据类型,当一个对象修改后,对另一个对象是没有影响的
实例之浅复制
static class Sheep implements Cloneable {
private String name;
private Integer age;
private String color;
private Sheep friend;
public Sheep getFriend() {
return friend;
}
public void setFriend(Sheep friend) {
this.friend = friend;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
@NonNull
@Override
protected Sheep clone() throws CloneNotSupportedException {
return (Sheep) super.clone();
}
/**
* 深复制 采用流的方式写入和读取
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
public Object deepClone() throws IOException,ClassNotFoundException{
//通过输出流进行数据的写入
ByteArrayOutputStream bos=new ByteArrayOutputStream();
ObjectOutputStream oos=new ObjectOutputStream(bos);
oos.writeObject(this);
//通过输入流进行读取
ByteArrayInputStream bis=new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois=new ObjectInputStream(bis);
Object obj = ois.readObject();
bos.flush();
bos.close();
oos.close();
bis.close();
ois.close();
return obj;
}
@Override
public String toString() {
return "Sheep{" +
"name='" + name + '\'' +
", age=" + age +
", color='" + color + '\'' +
", friend=" + friend +
'}';
}
}
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
Sheep s=new Sheep();
s.setName("ss");
s.friend=new Sheep();
s.friend.setName("喜洋洋");
Sheep s1= (Sheep) s.clone();
s.setName("原数据修改name");
s.friend.setName("你是谁");
s1.setName("复制对象修改数据");
System.out.println("原对象:"+s.toString());
System.out.println("复制对象:"+s1.toString());
}
//打印信息
原对象:Sheep{name='原数据修改name', age=null, color='null', friend=Sheep{name='你是谁', age=null, color='null', friend=null}}
复制对象:Sheep{name='复制对象修改数据', age=null, color='null', friend=Sheep{name='你是谁', age=null, color='null', friend=null}}
- 1.实现浅复制需要实现Cloneable接口,并重写clone()
- 2.对于基本数据类型,当一个对象修改时,对另外一个对象不会有影响;但是对引用数据类型,当一个对象修改时,另外一个对象的数据也会发生改变
标签:Sheep,Java,name,对象,color,拷贝,public,friend 来源: https://blog.csdn.net/meijing11/article/details/119065387