一:Java中创建对象的方式
1:使用new操作符创建对象。
2:使用clone()复制对象。
3:使用反序列化来创建对象。
4:反射机制创建对象。
5:Unsafe.allocateInstance()创建对象。
示例
/**
* <p>
* Java中创建对象的方式
* </p>
* @author: zhu.chen
* @date: 2020/7/27
* @version: v1.0.0
*/
public class CreateObjectTest {
public static void main(String[] args) throws CloneNotSupportedException, IllegalAccessException, InstantiationException, IOException, ClassNotFoundException {
// 1:通过new创建对象
Person newPerson = new Person("zhangsan", 1);
System.out.println(newPerson);
// 2:通过clone():属性需要实现Cloneable接口,并重写Object类的clone()。
Person clonePerson = (Person) newPerson.clone();
System.out.println(clonePerson);
// 3:通过序列化和反序列化:需要实现序列化接口Serializable
Person serializablePerson = serializablePerson();
System.out.println(serializablePerson);
// 4:通过反射创建对象:通过newInstance()来创建时,必须有无参构造函数。
Class clazz = Person.class;
Person reflectionPerson = (Person) clazz.newInstance();
reflectionPerson.setAge(2);
reflectionPerson.setName("xiaoming");
System.out.println(reflectionPerson);
// 5:Unsafe.allocateInstance
Person unsafePerson = (Person) unsafe.allocateInstance(Person.class);
unsafePerson.setName("xiaobai");
unsafePerson.setAge(5);
System.out.println(unsafePerson);
// 6:BeanUtils的拷贝
Person beanPerson = new Person();
BeanUtils.copyProperties(newPerson, beanPerson);
System.out.println(beanPerson);
}
/**
* 获取unsafe类
*/
static Unsafe unsafe;
static {
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe) field.get(null);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 序列化对象
*
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
private static Person serializablePerson() throws IOException, ClassNotFoundException {
/**
* 网络传输和磁盘IO会存在序列化对象来进行传输和存储。
* 适用场景:IO(网络IO、磁盘IO)
*/
// 序列化
Person person = new Person("xiaohong", 4);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt"));
oos.writeObject(person);
// 反序列化
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("person.txt"));
return (Person) ois.readObject();
}
private static class Person implements Cloneable, Serializable {
private static final long serialVersionUID = -5463972443328267182L;
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
}
注:同步更新于CreateObjectTest
二:Java的深浅拷贝
浅拷贝:如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址。
深拷贝:深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。
深浅拷贝.png
1:使用new操作符创建对象:深拷贝
2:使用clone()复制对象:深拷贝、浅拷贝(具体看写法)
3:使用反序列化来创建对象:深拷贝
4:反射机制创建对象:深拷贝
5:Unsafe.allocateInstance()创建对象:深拷贝
三:如何选择拷贝方式
对象的拷贝一般都是用第三方工具类实现,比如spring-beans中的BeanUtils#copyProperties。
1:如果对象的属性全是基本类型的,那么可以使用浅拷贝。
2:如果对象有引用属性,那就要基于具体的需求来选择浅拷贝还是深拷贝。如果对象引用任何时候都不会被改变,那么没必要使用深拷贝,只需要使用浅拷贝就行了。如果对象引用经常改变,那么就要使用深拷贝。











网友评论