常见的对象常见方法有4种:
- 使用new关键字
- 使用clone方法
- 反射机制
- 反序列化
其中采用1,3新建对象时会调用构造函数,2和4并不会调用构造函数
测试代码,看运行结果
简单的bean类 Car
public class Car implements Cloneable, Serializable { private String name; public void setName(String name) { this.name = name; } protected Object clone() throws CloneNotSupportedException { return super.clone(); } public Car(String name) { this.name = name; System.out.println("create car"); } public void run() { System.out.println(this.name + " is run !"); } }
测试类的Main方法
public static void main(String[] args) throw Exception {
//new 关键字创建对象
Car car1 = new Car("mike1");
car1.run();
System.out.println("=================");
//序列化
ObjectOutput objectOutput = new ObjectOutputStream(new FileOutputStream("Car"));
objectOutput.writeObject(car1);
objectOutput.close();
//
//clone 创建对象
Car car2 = (Car) car1.clone();
car2.setName("mike2");
car2.run();
System.out.println("=================");
//反射创建对象
Class carClass = Class.forName(Car.class.getName());
Object obj = carClass.getDeclaredConstructor(new Class[]{String.class}).newInstance("mike3");
Method method = obj.getClass().getMethod("run");
method.invoke(obj);
// Car car3 = (Car) carClass.getDeclaredConstructor(new Class[]{String.class}).newInstance("mike3");
// car3.run();
System.out.println("=================");
//反序列化创建对象
ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream("Car"));
Car car4 = (Car) inputStream.readObject();
car4.setName("mike4");
car4.run();
}
下面是测试代码输出结果
create car
mike1 is run !
=================
mike2 is run !
=================
create car
mike3 is run !
=================
mike4 is run !
从结果中可以得出最直接的结论,Clone和反序列化都没有执行类的构造函数。
Clone
clone拷贝对象返回的是一个新的对象,而不是一个对象的引用地址;拷贝对象已经包含原来对象的信息,而不是对象的初始信息,即每次拷贝动作不是针对一个全新对象的创建。
利用clone,在内存中进行数据块的拷贝,复制已有的对象,也是生成对象的一种方式。前提是类实现Cloneable接口,Cloneable接口没有任何方法,是一个空接口,也可以称这样的接口为标志接口,只有实现了该接口,才会支持clone操作。有的人也许会问了,java中的对象都有一个默认的父类Object。
Object中有一个clone方法,为什么还必须要实现Cloneable接口呢,这就是cloneable接口这个标志接口的意义,只有实现了这个接口才能实现复制操作,因为jvm在复制对象的时候,会检查对象的类是否实现了Cloneable这个接口,如果没有实现,则会报CloneNotSupportedException异常。类似这样的接口还有Serializable接口、RandomAccess接口等。
还有值得一提的是在执行clone操作的时候,不会调用构造函数。