List克隆返回的是浅拷贝的集合
前一段时间,代码中用到ArrayList的Clone,Java自定义对象的Clone是浅拷贝,所以把自定义对象重新实现了Clone,并且实现了深拷贝,最终还是栽倒了坑里。原来是因为ArrayList竟然也是浅拷贝。
复现
写个小例子来复现下,下面是集合中存放的对象User,实现了Cloneable接口,并实现了深拷贝:
static class UserName implements Cloneable {
public String fname;
public String lname;
public UserName(String fname, String lname) {
this.fname = fname;
this.lname = lname;
}
@Override
protected UserName clone() throws CloneNotSupportedException {
return (UserName) super.clone();
}
}
static class User implements Cloneable {
public UserName userName;
public User(UserName name) {
this.userName = name;
}
@Override
protected User clone() throws CloneNotSupportedException {
User user = (User) super.clone();
user.userName = userName.clone();
return user;
}
}
复制代码
当我们克隆集合的时候:
private static void wrongListClone() {
//初始化集合元素<小白>
ArrayList<User> users = new ArrayList<>();
User user = new User(new UserName("小", "白"));
users.add(user);
//先克隆,然后改变原对象的值为<小黑>,输出发现克隆对象也跟着变为<小黑>
List<User> usersClone = (ArrayList<User>) users.clone();
user.userName.lname = "黑";
usersClone.forEach(u -> System.out.println(u.userName.fname + u.userName.lname));
}
复制代码
执行后输出<小黑>,说明克隆集合对象和原集合指向的是同一个对象。
小黑
复制代码
解决方案
需要自己实现集合的Clone,新建立一个集合,遍历源集合生成每个对象的Clone,放入新集合。
private static ArrayList<User> cloneUsers(ArrayList<User> users) throws CloneNotSupportedException {
ArrayList<User> cloneList = new ArrayList<>();
for (User u : users) {
cloneList.add(u.clone());
}
return cloneList;
}
private static void rightListClone() throws CloneNotSupportedException {
//初始化集合元素<小白>
ArrayList<User> users = new ArrayList<>();
User user = new User(new UserName("小", "白"));
users.add(user);
//先克隆,然后改变原对象的值为<小黑>,输出克隆对象依然为<小白>
List<User> usersClone = cloneUsers(users);
user.userName.lname = "黑";
usersClone.forEach(u -> System.out.println(u.userName.fname + u.userName.lname));
}
复制代码
执行后输出<小白>,说明克隆集合对象和原集合指向的是不同的对象,克隆功能正常。
小白
复制代码
可执行完整示例代码
package fly.sample.clone;
import java.util.ArrayList;
import java.util.List;
/**
* Created by qryc on 2021/11/10
*/
public class CloneDemo {
public static void main(String[] args) throws Exception {
wrongListClone();
rightListClone();
}
static class UserName implements Cloneable {
public String fname;
public String lname;
public UserName(String fname, String lname) {
this.fname = fname;
this.lname = lname;
}
@Override
protected UserName clone() throws CloneNotSupportedException {
return (UserName) super.clone();
}
}
static class User implements Cloneable {
public UserName userName;
public User(UserName name) {
this.userName = name;
}
@Override
protected User clone() throws CloneNotSupportedException {
User user = (User) super.clone();
user.userName = userName.clone();
return user;
}
}
private static void wrongListClone() {
//初始化集合元素<小白>
ArrayList<User> users = new ArrayList<>();
User user = new User(new UserName("小", "白"));
users.add(user);
//先克隆,然后改变原对象的值为<小黑>,输出发现克隆对象也跟着变为<小黑>
List<User> usersClone = (ArrayList<User>) users.clone();
user.userName.lname = "黑";
usersClone.forEach(u -> System.out.println(u.userName.fname + u.userName.lname));
}
private static ArrayList<User> cloneUsers(ArrayList<User> users) throws CloneNotSupportedException {
ArrayList<User> cloneList = new ArrayList<>();
for (User u : users) {
cloneList.add(u.clone());
}
return cloneList;
}
private static void rightListClone() throws CloneNotSupportedException {
//初始化集合元素<小白>
ArrayList<User> users = new ArrayList<>();
User user = new User(new UserName("小", "白"));
users.add(user);
//先克隆,然后改变原对象的值为<小黑>,输出克隆对象依然为<小白>
List<User> usersClone = cloneUsers(users);
user.userName.lname = "黑";
usersClone.forEach(u -> System.out.println(u.userName.fname + u.userName.lname));
}
}
复制代码




近期评论