java - 为什么可以在 for...each 循环中修改自定义对象的 ArrayList
问题描述
我们有一个简单的自定义对象:
public class CustomObject {
public CustomObject(int myIntNumber, String myString) {
this.myIntNumber = myIntNumber ;
this.myString = myString;
}
private int myIntNumber;
private String myString;
public void setMyIntNumber(int myIntNumber) {
this.myIntNumber = myIntNumber;
}
public int getMyIntNumber() {
return myIntNumber;
}
public void setMyString(String myString) {
this.myString = myString;
}
public String getMyString() {
return myString;
}
public String toString() {
return "CustomObject [" + String.valueOf(myIntNumber) + ", "+ myString+"]" ;
}
}
并且,我们尝试使用 for...each 循环修改此类对象的 ArrayList。当不能以这种方式修改 String 对象或 Integer 对象的 ArrayList 时,为什么要修改列表中的对象?
我的测试代码:
import java.util.ArrayList;
public class TestTraveringListModification {
public static void main(String[] args) {
ArrayList<String> sList = new ArrayList<String>();
sList.add("String a");
sList.add("String b");
sList.add("C");
sList.add("D");
sList.add("String f");
sList.add("String e");
System.out.println("Before: "+sList);
for (String s : sList) {
s="asdf" ;
}
System.out.println("After: "+ sList);
ArrayList<CustomObject> objL = new ArrayList<CustomObject> () ;
objL.add(new CustomObject (1, "test") );
objL.add(new CustomObject (2, "jim") );
objL.add(new CustomObject (20, "dec") );
objL.add(new CustomObject (60, "what") );
System.out.println("before: "+ objL );
for(CustomObject co : objL ){
co.setMyIntNumber(-1);
co.setMyString("modified String");
}
System.out.println("after: "+objL);
ArrayList<Integer> numList = new ArrayList<Integer>();
numList.add(1);
numList.add(3);
numList.add(5);
numList.add(67);
numList.add(9598);
System.out.println("before: "+ numList);
for (Integer i : numList){
i = 8;
}
System.out.println("after: "+ numList);
}
}
运行此程序将产生以下输出:
Before: [String a, String b, C, D, String f, String e]
After: [String a, String b, C, D, String f, String e]
before: [CustomObject [1, test], CustomObject [2, jim], CustomObject [20, dec], CustomObject [60, what]]
after: [CustomObject [-1, modified String], CustomObject [-1, modified String], CustomObject [-1, modified String], CustomObject [-1, modified String]]
before: [1, 3, 5, 67, 9598]
项目清单
after: [1, 3, 5, 67, 9598]
那么,为什么我可以修改 objL 而不是 sList 或 numList ?
解决方案
因为重新分配和变异是两个不同的东西。
s = "asdf"
将改变所指s
的内容。它曾经包含对 的成员的引用sList
,现在它引用"asdf"
. 更改与 的成员无关sList
。
与i
和类似numList
,但不完全相同。numList
包含Integer
对象,从1
, 3
, 5
...自动装箱for
会将 Integer 对象值分配给i
. 如果您随后将值更改i
为 (autoboxed) Integer(8)
,它也不会影响numList
任何内容。
但是,使用co
and objL
,您会做一件非常不同的事情。您选择调用 on 上的方法,而不是重新分配co
给另一个对象(这不会影响 中的对象),然后碰巧改变了它们的状态。请注意,这里不是在修改,而是在修改它包含的对象。objL
co
objL
关键的见解是i
,co
并且s
不是相应列表的元素。它们包含可能是列表元素的值(但同样在自动拆箱的情况下,这也不成立)。
推荐阅读
- php - 如何在 laravel 中获得没有一个特定产品 ID 的所有产品类别?
- laravel - 如何转换 2021-05-24T04:44:56+00:00 格式的日期时间?
- javascript - 无法读取未定义反应复选框的“已检查”属性
- python - python函数中的运行时错误(列表,实践中的字符串混淆问题)
- azure - 在 ARM 模板 IPRestriction 中包含 Front Door ID
- python - 使用箭头控制步进电机
- flutter - Q 错误:Android 工具链 - 为 Android 设备开发
- dart - Bang 运算符与断言语句
- python - 卡在字符串编号部分..当我输入字符串时,代码返回错误,因为输入函数已被强制转换为整数
- azure - 为什么可以将资源移动到 Azure 中的只读资源组?