一、Object类的clone方法
1、说明
Object类的clone方法是native方法
什么是Native Method?简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C/C++语言
2、代码
protected native Object clone() throws CloneNotSupportedException;
二、利用系列化发序列化的clone方法
1、说明
被克隆的对象需要继承Serializable接口
2、代码
import java.io.*;
/**
* 深度clone工具类,被clone的类必须是序列化了,否则会报错
* 利用对象的序列化、反序列化达到深度clone
*/
public class CloneUtil {
public static <T extends Serializable> T clone(T obj) {
T clonedObj = null;
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(obj);
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
clonedObj = (T) ois.readObject();
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
return clonedObj;
}
}
三、实验对比
1、类对象
public class Identity implements Serializable {
private static final long serialVersionUID = 4980693168901248332L;
private String idNo;
private List<String> schoolingNames;
private Integer age;
public String getIdNo() {
return idNo;
}
public void setIdNo(String idNo) {
this.idNo = idNo;
}
public List<String> getSchoolingNames() {
return schoolingNames;
}
public void setSchoolingNames(List<String> schoolingNames) {
this.schoolingNames = schoolingNames;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
public class User implements Serializable, Cloneable{
private static final long serialVersionUID = 1835115164855723296L;
private String userName;
private String password;
private Identity identity;
@Override
public Object clone() throws CloneNotSupportedException{
return super.clone();
}
public Identity getIdentity() {
return identity;
}
public void setIdentity(Identity identity) {
this.identity = identity;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
2、 测试代码
public class CloneTest {
public static void main(String[] args) {
try {
test1();
System.out.println("======================");
test2();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
private static void test1() throws CloneNotSupportedException {
long start = System.currentTimeMillis();
// 封装user1
Identity identity = new Identity();
identity.setAge(10);
identity.setIdNo("00000000000000");
List<String> schoolNames = new ArrayList<>();
schoolNames.add("家里蹲大学");
identity.setSchoolingNames(schoolNames);
User user1 = new User();
user1.setUserName("wangteng");
user1.setPassword("123456");
user1.setIdentity(identity);
// 利用Object的原生clone()方法clone一个对象user2
User user2 = (User) user1.clone();
// 比较user1和user2的引用
boolean result1 = user1==user2;
System.out.println("user1 == user2 : " + result1);
// 比较user1和user2的简单类型的属性password属性(String类型,比较特殊点)
boolean result2 = user1.getPassword()==user2.getPassword();
System.out.println("user1.getPassword() == user2.getPassword() : " + result2);
// 比较user1和user2的复杂类型的属性identity属性
boolean result3 = user1.getIdentity()==user2.getIdentity();
System.out.println("user1.getIdentity() == user2.getIdentity() : " + result3);
System.out.println("花费时间:" + (System.currentTimeMillis()-start) + "ms");
}
private static void test2() throws CloneNotSupportedException {
long start = System.currentTimeMillis();
// 封装user1
Identity identity = new Identity();
identity.setAge(10);
identity.setIdNo("00000000000000");
List<String> schoolNames = new ArrayList<>();
schoolNames.add("家里蹲大学");
identity.setSchoolingNames(schoolNames);
User user1 = new User();
user1.setUserName("wangteng");
user1.setPassword("123456");
user1.setIdentity(identity);
// 利用对象的序列化、反序列化达到深度clone
User user2 = CloneUtil.clone(user1);
// 比较user1和user2的引用
boolean result1 = user1==user2;
System.out.println("user1 == user2 : " + result1);
// 比较user1和user2的简单类型的属性password属性(String类型,比较特殊点)
boolean result2 = user1.getPassword()==user2.getPassword();
System.out.println("user1.getPassword() == user2.getPassword() : " + result2);
// 比较user1和user2的复杂类型的属性identity属性
boolean result3 = user1.getIdentity()==user2.getIdentity();
System.out.println("user1.getIdentity() == user2.getIdentity() : " + result3);
System.out.println("花费时间:" + (System.currentTimeMillis()-start) + "ms");
}
}
3、输出
user1 == user2 : false
user1.getPassword() == user2.getPassword() : true
user1.getIdentity() == user2.getIdentity() : true
花费时间:3ms
======================
user1 == user2 : false
user1.getPassword() == user2.getPassword() : false
user1.getIdentity() == user2.getIdentity() : false
花费时间:65ms
四、说明
从上可以看出:
1、Object类的native方法clone()实现的是浅拷贝,序列化反序列化实现的是深拷贝。
2、二者从效率上来看,clone方法由于实现的是浅拷贝同时是native方法,所以效率远远比序列化反序列化的深拷贝来的高。
网友评论