在Java中,创建对象的几种方式包括:
-
使用new关键字创建对象
-
反射调用
-
克隆(clone)浅克隆
-
反序列化
-
MethodHand API
-
Unsafe 工具创建
其中,第一种方式是最常见的创建对象的方式,而其他方式则更多地用于一些特殊的场合。
具体使用方式如下:
给定一个类:
public class Teacher implements Cloneable, Serializable {
private Integer id;
private String name;
private Integer age;
public Teacher(Integer id, String name, Integer age) {
System.out.println("Teacher ... 构造");
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Teacher{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
1、使用 new 关键字:会使用构造方法
Teacher teacher1 = new Teacher(1, "张三", 25);
System.out.println("teacher1 = " + teacher1);
2、反射调用:会调用构造方法
Constructor<Teacher> constructor = Teacher.class
.getDeclaredConstructor(Integer.class,
String.class,
Integer.class);
Teacher teacher2 = constructor.newInstance(10, "李四", 26);
System.out.println("teacher2 = " + teacher2);
3、克隆:不会调用构造方法,需要实现 Cloneable 接口,并重写 clone 方法
Teacher teacher3 = (Teacher) teacher1.clone();
System.out.println("teacher3 = " + teacher3);
System.out.println(" teacher1 == teacher3 --->" + (teacher1 == teacher3));
4、使用反序列化:不会调用构造方法,需要实现 Serializable 接口
//使用序列化
byte[] bytes = serialize(teacher1);
Teacher teacher4 = (Teacher) deserialize(bytes);
System.out.println("teacher4 = " + teacher4);
System.out.println("teacher1 == teacher4 --->" + (teacher1 == teacher4));
/**
* 序列化
*
* @param teacher
* @return
* @throws IOException
*/
private static byte[] serialize(Teacher teacher) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(teacher);
byte[] bytes = bos.toByteArray();
return bytes;
}
/**
* 反序列化
*
* @param bytes
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
private static Object deserialize(byte[] bytes) throws IOException, ClassNotFoundException {
ObjectInputStream inputStream = new ObjectInputStream(new ByteArrayInputStream(bytes));
return inputStream.readObject();
}
5、MethodHandle API:会调用构造方法
// MethodHandle API
MethodHandle handle = MethodHandles.lookup().findConstructor(Teacher.class, MethodType.methodType(void.class, Integer.class, String.class, Integer.class));
Teacher teacher5 = (Teacher) handle.invoke(23, "小美", 18);
System.out.println("teacher5 = " + teacher5);