Java面试题——深拷贝和浅拷贝
在Java语言中,当我们需要拷贝一个Java对象的时候,常见的会有两种方式的拷贝:浅拷贝和深拷贝。 一、浅拷贝 浅拷贝只是拷贝了源对象的地址,所以源对象的任何值发生变化时,拷贝对象的值也会随之发生变化。  浅拷贝代码举例: User类
package deepcopyandshallowcopy;
public class User {
private String username;
private String password;
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
}
CopyTest1类
package deepcopyandshallowcopy;
public class CopyTest1 {
public static void main(String[] args) {
User user1 = new User();
user1.setUsername("浅拷贝");
user1.setPassword("123456");
User user2 = user1;
System.out.println("user1=" + user1);
System.out.println("user2=" + user2);
System.out.println("user1 username=" + user1.getUsername());
System.out.println("user2 username=" + user2.getUsername());
user2.setUsername("shallowcopy");
System.out.println("user1 username=" + user1.getUsername());
System.out.println("user2 username=" + user2.getUsername());
}
}
运行结果: 
二、深拷贝 深拷贝则是拷贝了源对象的所有值而不是地址,所以即使源对象的值发生任何变化时,拷贝对象的值也不会改变。  常见的几种深拷贝方式:
- 构造函数方式
- 重写clone方法
- Apache Commons Lang序列化
- Gson序列化
- Jackson序列化
1.构造函数方式 new的方式可以让每一个对象都是新创建的,他们之间互不干扰,但是new的方式在对象个数少的情况下,勉强能够使用,在创建对象过多时,对系统的开销很大,所以不推荐通过这种方式完成。 在上面的User类中添加无参和有参构造器,代码如下:
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
CopyTest2类
package deepcopyandshallowcopy;
public class CopyTest2 {
public static void main(String[] args) {
User user1 = new User("喜东东", "654789");
User user2 = new User("德善", "135789");
System.out.println("user1=" + user1);
System.out.println("user2=" + user2);
user1.setUsername("阿泽");
System.out.println("user1 username=" + user1.getUsername());
System.out.println("user2 username=" + user2.getUsername());
}
}
运行结果:  2.重写clone方法 重写clone方法对属性为String等数据类型可以进行深拷贝,针对于属性为对象类型的数据,不能进行深拷贝,只能进行浅拷贝。
(1)在重写Object父类继承而来的clone()方法,并修改为public
@Override
public User clone() throws CloneNotSupportedException {
return (User)super.clone();
}
(2)实现Cloneable接口来告诉JVM此类允许拷贝
public class User implements Cloneable{}
CopyTest3类
package deepcopyandshallowcopy;
public class CopyTest3 {
public static void main(String[] args) {
try {
User user1 = new User("喜东东", "654789");
User user2 = user1.clone();
System.out.println("user1=" + user1);
System.out.println("user2=" + user2);
System.out.println("user1 username=" + user1.getUsername());
System.out.println("user2 username=" + user2.getUsername());
user2.setUsername("xdd");
System.out.println("user1 username=" + user1.getUsername());
System.out.println("user2 username=" + user2.getUsername());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
运行结果: 
|