遍历循环遇到的问题

本文最后更新于:2021年10月6日 晚上

今天又是蠢蠢的一天,再再再再一次因为写错导致排查半天的错误

1.话不多说,直接复现了一下问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import java.util.ArrayList;
import java.util.List;

public class questionnair {
public static void main(String[] args) {
// 错误写法:循环体外复用一个对象
// User user = new User();
User user;
List<User> userList = new ArrayList<>();
for (int i = 10; i > 0; i--) {
// 正确写法 或 方案一:User user = new User();
// 方案二
user = new User();
user.setId(i);
user.setName("你猜" + i);
userList.add(user);
}
for (User user2 : userList) {
System.out.println(user2);
}
}

public static class User {
private Integer id;
private String name;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getName() {
return name;
}

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

2.打印结果

1
2
3
4
5
6
7
8
9
10
11
12
13
错误结果:此时想要的集合元素其实都是同一个对象;
questionnair$User@368239c8
questionnair$User@368239c8
questionnair$User@368239c8
questionnair$User@368239c8
questionnair$User@368239c8

正确结果:明显可以看出 这是正确放入集合中的元素
questionnair$User@368239c8
questionnair$User@9e89d68
questionnair$User@3b192d32
questionnair$User@16f65612
questionnair$User@311d617d

3.出现这种问题的原因所在:

  1. 我的想法:

    首先我想的是虽然都是同一个对象,但是我每次赋的都是新值且赋值前都放入了集合中,“按理说”应该是不同的元素。

  2. 实际上:

    因为只 new 了一个对象,所以在内存中只为这一个对象开辟了存储空间。而实例变量 user 是指向该对象存储空间的地址,例如 0X12345。当 i = 1 时,赋给它的值为 1;id = 1,name = “你猜 1”;虽然在下一轮循环中,重新赋了值,即 id = 2,name = “你猜 2”;但是放入集合中的两个元素,其实都是指向 0X12345,所以 list 中的元素 都是最新的同一个对象,自然就不是想要的结果。

  3. 正确的原因

    同理可知,每次循环 new 一个对象,并赋予它不同的值,得到的结果自然是不通的对象。不过需要注意的是,在循环体中声明对象,如方案一的方法 每次循环都会创建一份对象引用,如果循环次数就会非常消耗内存,更深的细节就设计 Jvm 底层远离了,就不做更多的叙述了,有兴趣了解的可以去查阅一下。

涉及到的知识点:Java 的值传递和对象地址传递,都是一些很基础的知识点,由此可见基础对于开发的重要性;

4.有更多理解和有错误所在的请不吝讲解,相互学习。


遍历循环遇到的问题
http://qingyux.cn/2021/08/16/遍历循环遇到的问题/
作者
柠檬薄荷
发布于
2021年8月16日
许可协议