本人以前被问到有哪些方法创建对象

我回答,new,反序列化,反射。后来才知道还有个克隆(汗颜哭

克隆clone,这个方法我经常在object类中看到,之前也一直没关注过它,直到最近看克隆的时候才开始关注

什么是克隆?

这得先讲解下new一个对象的原理,简单来说就是先在内存中分配一个对象(所要new的对象)大小的内存,然后通过构造方法往这个内存里面注入值,然后这个对象的引用

而clone与new相似,也是先在内存中分配一个对象大小的内存,然后根据原对象的值赋值给新对象。然后返回这个对象的引用

而要实现clone必须重写Object类中的clone方法,且实现Cloneable否则报CloneNotSupportedException异常。这个接口是个标记接口,即使接口内部没有任何方法

而clone克隆又分浅拷贝和深拷贝

浅拷贝的意思是简单的赋值数据,而不重新开辟新的对象,super.clone()直接调用这个方法为浅拷贝

深拷贝的意思的,先开辟对象在从原来对象中获取数据,赋值给新开辟的对象中

public class Person implements Cloneable{
	
	public String name;
	public int age;
	
	
	/**
	 * public 开放权限,从object继承过来是protected
	 * 若是类中有对象属性,应该实现深拷贝(先开辟对象在复制值),类中只有简单类型则直接调用父类super.clone()
	 */
	@Override
	public Object clone() throws CloneNotSupportedException {
		/*	
		 * 	1、执行super.clone()方法   先从内存中开辟一个对象的空间,
		 * 	在从原来对象中赋值给该对象,简单值传递。传递引用变量,这意味着都是浅拷贝
		 * 	这就意味着原来的对象的复杂类型的值发生改变则clone的对象里面的相同属性也将发送改变
		 * 	2、但是String除外String是无法改变对象内值的复杂类型,
		 * 	String类型发送改变也只是在内存中新创建一个字符串对象,将该对象的引用返回而原字符串还存在内存中!
		 * 	
		 */
		
		Person person = (Person)super.clone();//返回一个浅拷贝的对象
		person.name = new String(((Person)super.clone()).name);//手动new出新的对象出来并且赋值 
		//实际上String类型并不需要new一个新对象,因为无法改变String的值,所以无法导致原数据的改变而影响现在数据
		
		return person;
	}

	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
}

//需要克隆的对象必须实现Cloneable接口,否则报CloneNotSupportedException
public class School implements Cloneable{
	public Person person;
	public int number;
	
	/**
	 * 实现克隆的对象中如果有其他类的对象,需要调用其他类的clone方法
	 */
	@Override
	public Object clone() throws CloneNotSupportedException {
		School school = (School)super.clone();
		school.person = (Person)person.clone();
		return school;
	}

	public School(Person person, int number) {
		this.person = person;
		this.number = number;
	}
}

public class CloneTest {
	public static void main(String[] args) {
		Person p = new Person("wxt",12);
		try {
			Person p1 = (Person) p.clone();
			System.out.println(p1==p);			// false  不是相同对象
			System.out.println(p1.name.equals(p.name));  //true 值相同
			System.out.println(p1.name==p.name);  //false  name属性不是相同对象
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		
		/************************************/
		System.out.println("/************************************/");			// false  不是相同对象
		School school = new School(p,55);
		try {
			School s1 = (School)school.clone();
			System.out.println(school==s1);	                         // false  不是相同对象
			System.out.println(school.person.name.equals(s1.person.name));  //true person属性的name值相同
			System.out.println(school.person==s1.person);            //false  person属性不是相同对象
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
	}
}