Java的List的Clone竟然是浅拷贝

Java的List的Clone竟然是浅拷贝

1. List克隆返回的是浅拷贝的集合

前一段时间,代码中用到了Clone,Java中自定义对象默认的Clone是浅拷贝,所以重写了自定义对象的clone方法,实现了深拷贝。没想到还有一个坑,ArrayList的Clone竟然也是浅拷贝,集合本来想当然的认为一定是深拷贝。

复现

写个小例子来复现下,下面是集合中存放的对象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)); }

执行后输出<小黑>,说明克隆集合对象和原集合指向的是同一个对象。

小黑

2. 解决方案

需要自己实现集合的Clone,新建立一个集合,遍历源集合生成每个对象的Clone,放入新集合。

``` private static ArrayList cloneUsers(ArrayList users) throws CloneNotSupportedException { ArrayList cloneList = new ArrayList<>(); for (User u : users) { cloneList.add(u.clone()); } return cloneList; }

private static void rightListClone() throws CloneNotSupportedException { //初始化集合元素<小白> ArrayList users = new ArrayList<>(); User user = new User(new UserName("小", "白")); users.add(user); //先克隆,然后改变原对象的值为<小黑>,输出克隆对象依然为<小白> List usersClone = cloneUsers(users); user.userName.lname = "黑"; usersClone.forEach(u -> System.out.println(u.userName.fname + u.userName.lname)); } ```

执行后输出<小白>,说明克隆集合对象和原集合指向的是不同的对象,克隆功能正常。

小白

3. 可执行完整示例代码

``` 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));

}

}

```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值