Java集合中对象的复制-浅拷贝、深拷贝

浅拷贝: 对于仅仅是复制了引用(地址),换句话说,复制了之后,原来的变量和新的变量指向同一个东西,彼此之间的操作会互相影响,为浅拷贝

深拷贝:而如果是在堆中重新分配内存,拥有不同的地址,但是值是一样的,复制后的对象与原来的对象是完全隔离,互不影响,为深拷贝

深浅拷贝的主要区别就是:复制的是引用(地址)还是复制的是实例。

测试Bean

class Person implements Serializable {
    private int age;
    private String name;

    public Person() {
    }

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return this.name + "-->" + this.age;
    }
}

浅拷贝

循环复制

@Test
 public void test() {
     List<Person> list = new ArrayList<>();
     list.add(new Person(18, "zhangsan"));

     //循环复制
     List<Person> newList=new ArrayList<>(list.size());
     for(Person p : list){
         newList.add(p);
     }

     System.out.println(list);//[zhangsan-->18]
     System.out.println(newList);//[zhangsan-->18]

     System.out.println("---改变newList中Person的age,list中Person的age也被改变---");
     newList.get(0).setAge(20);

     System.out.println(list);//[zhangsan-->20]
     System.out.println(newList);//[zhangsan-->20]
 }

List实现类的构造方法

@Test
public void test() {
    List<Person> list = new ArrayList<>();
    list.add(new Person(18, "zhangsan"));

    //使用List实现类的构造方法
    List<Person> newList=new ArrayList<>(list);

    System.out.println(list);//[zhangsan-->18]
    System.out.println(newList);//[zhangsan-->18]

    System.out.println("---改变newList中Person的age,list中Person的age也被改变---");
    newList.get(0).setAge(20);

    System.out.println(list);//[zhangsan-->20]
    System.out.println(newList);//[zhangsan-->20]
}

addAll()方法

@Test
public void test() {
    List<Person> list = new ArrayList<>();
    list.add(new Person(18, "zhangsan"));

    //使用addAll()方法
    List<Person> newList=new ArrayList<>();
    newList.addAll(list);

    System.out.println(list);//[zhangsan-->18]
    System.out.println(newList);//[zhangsan-->18]

    System.out.println("---改变newList中Person的age,list中Person的age也被改变---");
    newList.get(0).setAge(20);

    System.out.println(list);//[zhangsan-->20]
    System.out.println(newList);//[zhangsan-->20]
}

System.arraycopy()方法

@Test
public void test() {
    List<Person> list = new ArrayList<>();
    list.add(new Person(18, "zhangsan"));

    //使用System.arraycopy()方法
    Person[] array = list.toArray(new Person[0]);
    Person[] newArray=new Person[array.length];
    System.arraycopy(array, 0, newArray, 0, array.length);
    List<Person> newList = Arrays.asList(newArray);

    System.out.println(list);//[zhangsan-->18]
    System.out.println(newList);//[zhangsan-->18]

    System.out.println("---改变newList中Person的age,list中Person的age也被改变---");
    newList.get(0).setAge(20);

    System.out.println(list);//[zhangsan-->20]
    System.out.println(newList);//[zhangsan-->20]
}

clone()方法

@Test
public void test() {
    List<Person> list = new ArrayList<>();
    list.add(new Person(18, "zhangsan"));

    //使用clone()方法
    Person[] array = list.toArray(new Person[0]);
    Person[] newArray = array.clone();

    List<Person> newList = Arrays.asList(newArray);

    System.out.println(list);//[zhangsan-->18]
    System.out.println(newList);//[zhangsan-->18]

    System.out.println("---改变newList中Person的age,list中Person的age也被改变---");
    newList.get(0).setAge(20);

    System.out.println(list);//[zhangsan-->20]
    System.out.println(newList);//[zhangsan-->20]
}

深拷贝

序列化方法

对象需要序列化(实现Serializable)

public <T> List<T> depCopy(List<T> srcList) {
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
        try {
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(srcList);
            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream inStream = new ObjectInputStream(byteIn);
            List<T> destList = (List<T>) inStream.readObject();
            return destList;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
@Test
public void test() {
    List<Person> list = new ArrayList<>();
    list.add(new Person(18, "zhangsan"));

    //使用序列化方法
    List<Person> newList = depCopy(list);

    System.out.println(list);//[zhangsan-->18]
    System.out.println(newList);//[zhangsan-->18]

    System.out.println("---改变newList中Person的age,list中Person的age不被改变---");
    newList.get(0).setAge(20);

    System.out.println(list);//[zhangsan-->18]
    System.out.println(newList);//[zhangsan-->20]
}

实现cloneable接口和重写clone方法

有限制性,要先声明List是保存的什么对象,并且当碰到对象里面还持有List集合的时候,则不管用

class Person implements Cloneable, Serializable {
    private int age;
    private String name;

    public Person() {
    }

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return this.name + "-->" + this.age;
    }

    @Override
    public Object clone() {
        Person o = null;
        try {
            o = (Person) super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return o;
    }
}
@Test
public void test() {
   List<Person> list = new ArrayList<>();
   list.add(new Person(18, "zhangsan"));

   //重写clone方法
   List<Person> newList = new ArrayList<>();
   for (int i = 0; i < list.size(); i++) {
       Person clone = (Person) list.get(i).clone();
       newList.add(clone);
   }

   System.out.println(list);//[zhangsan-->18]
   System.out.println(newList);//[zhangsan-->18]

   System.out.println("---改变newList中Person的age,list中Person的age不被改变---");
   newList.get(0).setAge(20);

   System.out.println(list);//[zhangsan-->18]
   System.out.println(newList);//[zhangsan-->20]
}

基础类型没有深浅拷贝

@Test
public void test() {
    List<String> list = new ArrayList<>();
    list.add("A");
    list.add("B");
    list.add("C");

    List<String> newList = new ArrayList<>(list.size());
    newList.addAll(list);

    System.out.println(list);
    System.out.println(newList);

    System.out.println("---基础类型没有深浅拷贝---");
    newList.set(0, "AA");

    System.out.println(list);
    System.out.println(newList);
}

Java提高篇——对象克隆(复制)

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java深拷贝浅拷贝是用来复制对象的两种不同方式。深拷贝会对所有数据类型进行拷贝,包括对象所包含的内部对象,而浅拷贝只是简单地复制对象的引用。在Java,实现深拷贝的方式有几种方法。 一种方式是对浅拷贝进行加强,即对对象的引用属性进行clone操作。这种方式需要确保对象的引用属性实现了Cloneable接口,并重写了clone方法。 另一种方式是通过序列化来实现深拷贝。通过将对象序列化为字节流,然后再反序列化为一个新的对象,可以实现对对象的全部拷贝。需要注意的是,transient变量无法被序列化,所以使用这种方式将无法拷贝transient变量。 还可以借助第三方工具类来实现深拷贝。这些工具类通常提供了一些方法来实现对象深拷贝,例如Apache Commons Lang库的SerializationUtils类。 选择深拷贝还是浅拷贝取决于具体的需求。如果对象属性全是基本类型,可以使用浅拷贝。如果对象有引用属性,并且这些引用属性可能会被改变,就需要使用深拷贝。没有一成不变的规则,一切都取决于具体的需求。 在Java,可以通过实现Serializable接口和Cloneable接口来实现深拷贝。例如,可以在User类实现Serializable接口,并重写clone方法来实现深拷贝。借助三方工具类也是一种实现深拷贝的方式。 #### 引用[.reference_title] - *1* *3* [JAVA 浅拷贝深拷贝](https://blog.csdn.net/skystep/article/details/126211689)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Java深拷贝浅拷贝](https://blog.csdn.net/qq_43460095/article/details/125766762)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值