java object clone

java clone

Why clone

We need to use an object in many cases to record another object of the current state of the object may have many attributes, if we go one by one set, not only inconvenient and inefficient, we look at a beginner might encounter problem

class Person{
	String name;
    int age;
	
	public Person() {}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	
}

@Test
	public void test2() {
		Person p1=new Person("tom",20);
		Person p2=p1;
		System.out.println(p1);
		System.out.println(p2);
		System.out.println("---------");
		p1.age=30;
		System.out.println(p1);
		System.out.println(p2);
	}
输出:
Person [name=tom, age=20]
Person [name=tom, age=20]
---------
Person [name=tom, age=30]
Person [name=tom, age=30]

Maybe some people think Person p2 = p1 such a way that you can clone an object, this idea is wrong, this assignment only use the equal sign of the assignment p1 p2 address to the object, then point to p1 and p2 a heap of the same object, therefore, modify the p1 p2 then it changed

If a property to a manual setting is not only cumbersome, but may also have property attributes, change is not easy

public void test2() {
		Person p1=new Person("tom",20);
		Person p2=new Person();
		p2.age=p1.age;
		p2.name=p1.name;
	}

Here Person attribute hierarchy is very simple to modify it looks simple, but a property of type Address Person if more, then you must manually modify the Address and go to a new assignment properties, if the nested hierarchy attribute deep, and on very difficult

So we can use the clone method to clone objects provided by Object, because the clone method is a protected keywords modified, if we want to use outside the class will need to override the parent class, Object clone method is a modification of the native keyword the method, which calls the other languages ​​of the method, high efficiency, it is noteworthy thing is to clone the object class must implement the Cloneable interface, this interface is a marker interface, which does not define any method, if nothing implement the Cloneable interface using the clone method throws an exception CloneNotSupportedException

Shallow clone

If the properties of the prototype object is a value type, then copy to clone an object, if the property is a reference type, the reference assigned to the cloned object properties

class Person implements Cloneable{//必须实现Cloneable接口
	String name;
    int age;
	
	public Person() {}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	@Override
	protected Object clone(){
		Person p=null;
		try {
			p=(Person)super.clone();
		}catch(CloneNotSupportedException e) {//实现了Cloneable接口这个异常就不可能发生
			e.printStackTrace();
		}
		return p;
	}
	
}

@Test
	public void test2() {
		Person p1=new Person("tom",20);
		Person p2=(Person)p1.clone();
		System.out.println(p1);
		System.out.println(p2);
		System.out.println("---------");
		p1.age=30;
		System.out.println(p1);
		System.out.println(p2);
	}
输出:
Person [name=tom, age=20]
Person [name=tom, age=20]
---------
Person [name=tom, age=30]
Person [name=tom, age=20]

This clone in class Object provides the property value type all the time will not be a problem, but if there is a reference type class property will be a problem

class Person implements Cloneable{
	String name;
    int age;
    Address address;
	
	public Person() {}
	public Person(String name, int age,Address addr) {
		super();
		this.name = name;
		this.age = age;
		this.address=addr;
	}
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
	}
	@Override
	protected Object clone(){
		Person p=null;
		try {
			p=(Person)super.clone();
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return p;
	}
	
}
class Address{
	String addr;

	public Address(String addr) {
		super();
		this.addr = addr;
	}

	@Override
	public String toString() {
		return "Address [addr=" + addr + "]";
	}
	
}

@Test
	public void test2() {
		Address addr=new Address("成都市郫都区");
		Person p1=new Person("tom",20,addr);
		Person p2=(Person)p1.clone();
		System.out.println(p1);
		System.out.println(p2);
		System.out.println("---------");
		p1.address.addr="成都市金牛区";
		System.out.println(p1);
		System.out.println(p2);
	}
输出:
Person [name=tom, age=20, address=Address [addr=成都市郫都区]]
Person [name=tom, age=20, address=Address [addr=成都市郫都区]]
---------
Person [name=tom, age=20, address=Address [addr=成都市金牛区]]
Person [name=tom, age=20, address=Address [addr=成都市金牛区]]

P1 modify the address according cloned p2 p1 of the address has changed, this is referred to as cloned object's properties is a reference type, it will only copy references, and this situation generally we do not want, so You need to use deep clone

Deep clone

1. all references clone clone types override method

Here reference type override method clone, cloning refers to the object itself is a reference type attribute must override clone method and reference type reference type is also necessary to be rewritten, and the article must be explicitly used in the method clone

class Person implements Cloneable{
	String name;
    int age;
    Address address;//这个属性是引用类型,必须实现Cloneable接口重写clone方法
	
	public Person() {}
	public Person(String name, int age,Address addr) {
		super();
		this.name = name;
		this.age = age;
		this.address=addr;
	}
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
	}
	@Override
	protected Object clone(){
		Person p=null;
		try {
			p=(Person)super.clone();
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
      //显式调用克隆引用数据类型
		p.address=(Address)address.clone();
		return p;
	}
	
}
class Address implements Cloneable{
	String addr;

	public Address(String addr) {
		super();
		this.addr = addr;
	}

	@Override
	public String toString() {
		return "Address [addr=" + addr + "]";
	}

	@Override
	protected Object clone() {
		Address addr=null;
		try {
			addr=(Address)super.clone();
		}catch(CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return addr;
	}
	
}

@Test
	public void test2() {
		Address addr=new Address("成都市郫都区");
		Person p1=new Person("tom",20,addr);
		Person p2=(Person)p1.clone();
		System.out.println(p1);
		System.out.println(p2);
		System.out.println("---------");
		p1.address.addr="成都市金牛区";
		System.out.println(p1);
		System.out.println(p2);
	}
输出:
Person [name=tom, age=20, address=Address [addr=成都市郫都区]]
Person [name=tom, age=20, address=Address [addr=成都市郫都区]]
---------
Person [name=tom, age=20, address=Address [addr=成都市金牛区]]
Person [name=tom, age=20, address=Address [addr=成都市金牛区]]

Methods using the sequence

Need to clone object class must implement the Serializable interface, which is a marker interface, the interface does not have any way to achieve the class of this method may be written to the object representation of this class to the IO stream, so long objects in the network can be mail or save to a local disk

class Person implements Cloneable,Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 8990580911834489134L;
	String name;
    int age;
    Address address;
	
	public Person() {}
	public Person(String name, int age,Address addr) {
		super();
		this.name = name;
		this.age = age;
		this.address=addr;
	}
	
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + ", address=" + address + "]";
	}
	@Override
	protected Object clone(){
		Person p=null;
		try {
			//将对象写入流中
			ByteArrayOutputStream baos=new ByteArrayOutputStream();
			ObjectOutputStream oos=new ObjectOutputStream(baos);
			oos.writeObject(this);
			//将对象从流中读取出来
			ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
			ObjectInputStream ois=new ObjectInputStream(bais);
			p=(Person)ois.readObject();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return p;
	}
	
}
class Address implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 328854588872604721L;
	String addr;

	public Address(String addr) {
		super();
		this.addr = addr;
	}

	@Override
	public String toString() {
		return "Address [addr=" + addr + "]";
	}
}

@Test
	public void test2() {
		Address addr=new Address("成都市郫都区");
		Person p1=new Person("tom",20,addr);
		Person p2=(Person)p1.clone();
		System.out.println(p1);
		System.out.println(p2);
		System.out.println("---------");
		p1.address.addr="成都市金牛区";


		System.out.println(p1);
		System.out.println(p2);
	}
输出:
Person [name=tom, age=20, address=Address [addr=成都市郫都区]]
Person [name=tom, age=20, address=Address [addr=成都市郫都区]]
---------
Person [name=tom, age=20, address=Address [addr=成都市金牛区]]
Person [name=tom, age=20, address=Address [addr=成都市郫都区]]

Guess you like

Origin www.cnblogs.com/moyuduo/p/12670541.html