一个有点奇怪的ArrayList的问题,请帮忙看一看。

时间:2022-09-06 14:15:33
有类如下
//a simple bean
class sbean {
   String username;
//Getter and Setter 省略。
}
连接数据库取数据
库数据如下:
username
chen8m
kok
admin
//从数据库里取数据存在BEAN里面,再放在ArrayList
里面,但最后取出来username却变成了全部都是admin了。

Class.forName("com.mysql.jdbc.Driver");

String url = "jdbc:mysql://localhost:3306/strust";
String user = "root";
String password = "root";

Connection con = DriverManager.getConnection(url,user,password);

Statement stat = con.createStatement();

String sql = "select * from userInfor";

ResultSet result = stat.executeQuery(sql);
ArrayList alluser = new ArrayList();
userInfor temp = new userInfor();
while (result.next()) {
System.out.print(result.getString("username"));
System.out.print(" ");
temp.setUsername(result.getString("username"));
alluser.add(temp);
}
for (int i=0; i<alluser.size(); i++) {
userInfor t = (userInfor)alluser.get(i);
System.out.println(t.getUsername()+"--"+i);

}
//但是下面的代码改变了一点点就OK了。
Class.forName("com.mysql.jdbc.Driver");

String url = "jdbc:mysql://localhost:3306/strust";
String user = "root";
String password = "root";

Connection con = DriverManager.getConnection(url,user,password);

Statement stat = con.createStatement();

String sql = "select * from userInfor";

ResultSet result = stat.executeQuery(sql);
ArrayList alluser = new ArrayList();
//在这里做改变,把TEMP放在了循环里就OK了。
while (result.next()) {
userInfor temp = new userInfor(); System.out.print(result.getString("username"));
System.out.print(" ");
temp.setUsername(result.getString("username"));
alluser.add(temp);
}
for (int i=0; i<alluser.size(); i++) {
userInfor t = (userInfor)alluser.get(i);
System.out.println(t.getUsername()+"--"+i);

}
打字的框好小啊,都不知道问题有没有说清楚,
请看到的高手帮忙耐心看看,
问题是解决了,但就是不明白是为什么。
上一段代码调试的时候,明明都存在LIST里是对的
就是存到最后一个整个LIST就都变了。
望高手帮忙了,小弟在此谢过。


4 个解决方案

#1


调试的时候里面的值当然是变的啊,对同一个实例而言,你存放在ArrayList里面的始终是同一个对象啊!

#2


Java 中的对象是引用类型的,通俗点说,变量名中存放的是其数据的内存地址,它的值是存放在另外一块空间上的。

在第一段程序中,List 添加了很多的 temp(实际上添加了 temp 的内存地址),也就是说,List 中添加了很多相同的 temp,但是 temp 的 username 最终是指向最后一个的,所以前面存放在 List 中的 temp 的 username 值也就随之改变了,具体的引用关系参见下图(空白部分只能用.代替)。

-------
list(0) --------+
------- ........|.. ------- ...... ----------
list(1) --------+--> temp --------> username
------- ........|.. ------- ...... ----------
list(n) --------+
-------


而第二段程序中,temp 的作用范围仅在 { } 内,每循环一次就重新生成不同的对象,所以添加到最后也是不同的,这是正确的方法,为了与上一段进行比较,引用关系如下:

------- ........... ------- ...... ----------
list(0) -----------> temp --------> username
------- ........... ------- ...... ----------
list(1) -----------> temp --------> username
-------............ ------- ...... ----------
list(n) -----------> temp --------> username
------- ........... ------- ...... ----------

#3


temp = new userInfor();必须放在循环中的头部,因为ArrayList存储的时候,只会存储temp的数据地址,如果不把temp = new userInfor();放在循环中,每次循环将对同一块地址进行操作,即每次循环都会将上次循环的数据覆盖掉,所以要对对象temp在每次循环中都要重新new一下。

#4


谢谢了,各位,
明白了。学习了

#1


调试的时候里面的值当然是变的啊,对同一个实例而言,你存放在ArrayList里面的始终是同一个对象啊!

#2


Java 中的对象是引用类型的,通俗点说,变量名中存放的是其数据的内存地址,它的值是存放在另外一块空间上的。

在第一段程序中,List 添加了很多的 temp(实际上添加了 temp 的内存地址),也就是说,List 中添加了很多相同的 temp,但是 temp 的 username 最终是指向最后一个的,所以前面存放在 List 中的 temp 的 username 值也就随之改变了,具体的引用关系参见下图(空白部分只能用.代替)。

-------
list(0) --------+
------- ........|.. ------- ...... ----------
list(1) --------+--> temp --------> username
------- ........|.. ------- ...... ----------
list(n) --------+
-------


而第二段程序中,temp 的作用范围仅在 { } 内,每循环一次就重新生成不同的对象,所以添加到最后也是不同的,这是正确的方法,为了与上一段进行比较,引用关系如下:

------- ........... ------- ...... ----------
list(0) -----------> temp --------> username
------- ........... ------- ...... ----------
list(1) -----------> temp --------> username
-------............ ------- ...... ----------
list(n) -----------> temp --------> username
------- ........... ------- ...... ----------

#3


temp = new userInfor();必须放在循环中的头部,因为ArrayList存储的时候,只会存储temp的数据地址,如果不把temp = new userInfor();放在循环中,每次循环将对同一块地址进行操作,即每次循环都会将上次循环的数据覆盖掉,所以要对对象temp在每次循环中都要重新new一下。

#4


谢谢了,各位,
明白了。学习了