把对象添加到集合中,然后再修改对象,会发生什么呢?
下面分别看一下修改对象属性值和修改对象引用后的效果。
案例一,修改对象属性值
创建几个对象,添加到List中,然后修改对象的属性值,那么List中的元素的属性值会随之改变,比如下面的例子:
public static void test1() {
List<Order> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Order order = new Order();
order.setId(i); //id设为0,1,2
list.add(order);
order.setId(i * 2); //id改为0,2,4
}
for (int i = 0; i < 3; i++) {
Order order = list.get(i);
System.out.println(i + ":" + order.getId());
}
}
输出的结果是:
0:0
1:2
2:4
原理很简单,根据Java的内存原理,栈中保存对象的引用,堆中保存对象本身,此例中List的元素是指向堆中具体对象的引用,堆中的对象属性值改了,List中的元素自然也跟着改了。
用图来说就是这样的:
图1
案例二,修改对象引用
创建几个对象,添加到List中,然后修改对象引用,那么List中的元素引用不会随之改变,比如下面的例子:
public static void test2() {
List<Order> utilList = new ArrayList<>(); //备用List
for (int i = 10; i < 13; i++) {
Order order = new Order();
order.setId(i); //id值为10,11,12
utilList.add(order);
}
List<Order> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Order order = new Order();
order.setId(i); //id值为0,1,2
list.add(order);
order = utilList.get(i); //添加到list后,修改引用,指向备用List的元素
}
for (int i = 0; i < list.size(); i++) {
Order order = list.get(i);
System.out.println(i + ":" + order.getId());
}
}
输出的结果:
0:0
1:1
2:2
注意,list中的元素并没有因为对象修改引用而变成10,11,12,由此看来栈中的引用是直接指向堆中的对象,而不是指向栈中的引用。
用图来说明:
以下是错误的图:
以下是正确的图:
在此例中,即使把对象设为null,list中的元素也不会改变,小心内存泄露。
结合以上两个案例,往list中添加元素后如果还要对元素对象进行修改,小心为上。