解释为什么使用循环中使用list.add(),会出现List出现数据全是最后插入的那一条数据

一、 错误案例

1.1 测试使用的person对象

 public static class Person{
        private String name;
        private String gender;
        private Integer age;

        public String getName() {
            return name;
        }

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

        public String getGender() {
            return gender;
        }

        public void setGender(String gender) {
            this.gender = gender;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }
		
		 @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", gender='" + gender + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

1.2 list.add()的错误展示

 public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        Person person = new Person();
        for(int i=0;i<4;i++){
            person.setName("A"+i+i+i+i);
            person.setGender("男"+i+i+i+i);
            person.setAge(Integer.valueOf((""+i+i+i+i)));
            personList.add(person);
        }
        personList.forEach(System.out::println);
    }

1.3 你认为的结果

Person{name='A0000', gender='男0000', age=0}
Person{name='A1111', gender='男1111', age=1111}
Person{name='A2222', gender='男2222', age=2222}
Person{name='A3333', gender='男3333', age=3333}

1.4 实际结果

Person{name='A3333', gender='男3333', age=3333}
Person{name='A3333', gender='男3333', age=3333}
Person{name='A3333', gender='男3333', age=3333}
Person{name='A3333', gender='男3333', age=3333}

二、解决方案

2.1 简单粗暴

    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        for(int i=0;i<4;i++){
            Person person = new Person();
            person.setName("A"+i+i+i+i);
            person.setGender("男"+i+i+i+i);
            person.setAge(Integer.valueOf((""+i+i+i+i)));
            personList.add(person);
        }
        personList.forEach(System.out::println);
    }

也就是把1位置的代码移动到2位置,把1位置的代码删除
在这里插入图片描述

三、为什么会出现这种情况

3.1 原理

       因为这Java的面对对象的,而对象之间的传递都是传的的引用,这个引用其实也就是地址你在循环之外new了一个对象,而这个对象只有一个地址,每一次循环你都会把你这个对象放入到List中,这样你的集合里面其实存放的都只是一个地址。而你每次循环时都会改变这个对象的内容,但是地址还是那个地址,知道循环最后一次改变了对象的内容,之后不会再变动了。最终,集合里存放的都是同一个地址,而同一个地址找到的是同一个内容,而内容被最后一次循环改变之后就不会再变动。最终打印出来的结果就是全部重复的最后一次的结果。
     所以解决办法是,每次循环都需要new一个新的对象,用新对象来封装新数据,才不会出现重复的现象。

3.2 基于原理的效果呈现

3.2.1 代码

这里没有再Person对象里重写toString方法,这样最终打印出来的就是对象的(引用)/地址

public class MyTest {
    public static class Person{
        private String name;
        private String gender;
        private Integer age;

        public String getName() {
            return name;
        }

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

        public String getGender() {
            return gender;
        }

        public void setGender(String gender) {
            this.gender = gender;
        }

        public Integer getAge() {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age;
        }
		//注意:这里和上面代码的区别在于没有重写toString
       
    }

    public static void main(String[] args) {
        List<Person> personList = new ArrayList<>();
        Person person = new Person();
        for(int i=0;i<4;i++){
            person.setName("A"+i+i+i+i);
            person.setGender("男"+i+i+i+i);
            person.setAge(Integer.valueOf((""+i+i+i+i)));
            personList.add(person);
        }
        personList.forEach(System.out::println);
    }
}
3.2.2 结果

结果表示,放入集合的都是对象的引用,也就是地址,这些地址全部是一样的

com.example.demo.MyTest$Person@1a93a7ca
com.example.demo.MyTest$Person@1a93a7ca
com.example.demo.MyTest$Person@1a93a7ca
com.example.demo.MyTest$Person@1a93a7ca

如果我们,按照上述的解决方案,也就是在每次循环时,在里面new一个对象,在看一下结果

com.example.demo.MyTest$Person@1a93a7ca
com.example.demo.MyTest$Person@3d82c5f3
com.example.demo.MyTest$Person@2b05039f
com.example.demo.MyTest$Person@61e717c2

仔细观察,地址各不相同,所以根据地址找到的内容也不一样

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值