new ArrayList<>(Collection<? extends E> c)构造函数不生效;list深拷贝和浅拷贝;new ArrayList<>() 会改变原值;

1. 问题引入

  前两天一同事问了我一个问题大致是 List newList = new ArrayList<对象>(list); 然后对newList中的对象进行了一系列的操作,之后回头看 list 对象的时候,里面相同的值竟然也被修改了。

2. 问题复现及分析

2.1 newArrayList<基本类型或String>() ,下述基本对象为 String (此处没有问题)

string基本对象

2.2 newArrayList<对象>() ,下述基本对象 (此处有问题

对象方式
依据以往使用list 的经验, 第二张图的第二行应该输出张三而不是王五,然后同事就问我是为啥。 为啥呢我说这不是 吃了有经验的亏(基本类型或String是没问题的)[狗头] ,其实有的小伙伴可能已经知道了这是对象 copy问题

2.2 浅copy 和 深copy

  浅copy是指对象复制的时候,简单类型会直接copy值,对象类型的数据只copy指针引用,这个对象里面的属性不会copy;
  深copy是指对象复制的时候,简单类型会直接copy值,对象类型的数据会copy新对象;
   java默认的copy方式是浅copy,也就是说上述二截图中的Student 不管你newArray<Student>(studentList); 不管你 new多少次,实际上 student只有一个,所以你改动任意一个则都会改动

3. 解决方案

3.1 原生 clone 方法(不推荐)

   两大步骤,实现 Cloneable 重写 clone实现,但是这种方式比较麻烦,不仅要自己实现,而且当类中还有类的时候依旧需要重复上述操作。由于ArrayList 属性情况特殊,此种方式不太可行,用另一种方式来说明:

1.Student 类

	
	public class Student implements Cloneable {
    private String name;
    private Integer age;
    // 学科
    private Discipline discipline;

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public Discipline getDiscipline() {
        return discipline;
    }

    public void setDiscipline(Discipline discipline) {
        this.discipline = discipline;
    }
 	@Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Student{");
        sb.append("name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append(", discipline=").append(discipline);
        sb.append('}');
        return sb.toString();
    }

 @Override
    protected Object clone() {
        // 原生clone
        try {
            return super.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return null;


        // 重新后
//        Student str = null;
//        try {
//            str = (Student) super.clone();
//            Discipline cloneDiscipline = (Discipline) discipline.clone();
//            str.discipline = cloneDiscipline;
//            return str;
//        } catch (CloneNotSupportedException e) {
//            e.printStackTrace();
//        }
//        return str;
    }
  

2. Discipline 学科类


public class Discipline implements Cloneable {
    private String name;

    public String getName() {
        return name;
    }

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

  @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("Discipline{");
        sb.append("name='").append(name).append('\'');
        sb.append('}');
        return sb.toString();
    }
    
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

3.测试方法

 public static void main(String[] args) {
	 Student student = new Student();
        student.setName("张三");
        student.setDiscipline(new Discipline().setName("语文"));
        System.out.println("原student: " + student);
        Student student1 = (Student) student.clone();
        student1.getDiscipline().setName("数学");
        System.out.println("修改后student: " + student);
        System.out.println("student1:" + student1);
    }

4. 原生clone 输出结果

未实现clone

5.修改后的clone方法的执行结果

修改后结果

3.2 借助序列化(推荐)

3.2.1 可以借助三方工具包来实现 比如fastjson 、 jackson 等

先导包 再实现

// 导包
<dependency>
	<groupId>com.alibaba</groupId>
	<artifactId>fastjson</artifactId>
	<version>1.2.68</version>
</dependency>

// 实现 对象方式
 String studentStr = JSONObject.toJSONString(student);
 student = JSONObject.parseObject(studentStr, Student.class);
// 实现数组方式
String studentListStr = JSONArray.toJSONString(studentList);
List<Student> students = JSONArray.parseArray(studentListStr, Student.class);

3.2.2 自己实现(不建议)

  自己实现借助io流 比较费时不建议使用

4. 总结

   ArrayList<对象>(Collection<? extends E> c) 是浅copy,泛型是对象的时候只copy引用;
  深copy常用方式,实现 Cloneable 重写clone接口;借助三方序列化工具;

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值