Java中添加到List的对象是否可修改?底层原理咨询
Java List元素添加机制核心原理
Java所有参数传递都是值传递,不存在引用传递。对于引用类型,传递的值是「对象在堆内存中的内存地址引用」,而非对象本身;对于基本类型,传递的值就是字面量本身。
引用类型添加到List的逻辑(对应int[]数组示例)
代码示例:
List<int[]> list = new ArrayList<>(); int[] element = {2,3}; list.add(element); System.out.println(list); //[[2,3]] element[1] = 45; System.out.println(list); //[[2,45]]
int数组属于引用类型,声明int[] element = {2,3}时,element变量存储的是堆内存中该数组的地址。调用list.add(element)时,只会把element存储的地址值复制一份存入List的底层数组,不会复制整个数组对象本身。
此时List中存储的地址和element变量存储的地址指向同一个堆中的数组对象,通过element修改数组元素后,List通过同一地址访问到的自然是修改后的数组,所以输出结果会同步变化。
基本类型/包装类添加到List的逻辑(对应Integer示例)
代码示例:
List<Integer> list = new ArrayList<>(); int obj = 25; list.add(obj); System.out.println(list); //[25] obj=56; System.out.println(list); //still [25]
List不支持直接存储基本类型,传入int值时会自动触发自动装箱逻辑,等价于执行list.add(Integer.valueOf(obj)),会生成一个全新的Integer对象存储25这个值,再把该新对象的地址存入List,和原本的int类型obj变量已经没有任何关联。
后续给obj赋值为56,只是修改了obj这个基本类型变量存储的字面量,完全不会影响到之前自动装箱生成、存在List中的Integer对象,所以List的输出不会变化。
核心总结
- List的
add方法默认是浅拷贝逻辑,存入引用类型时仅复制对象的内存地址副本,和原引用指向同一个堆对象,修改原对象的内部属性/元素时,List中对应元素会同步变化 - 传入基本类型时会触发自动装箱,生成独立的包装类对象存入List,后续修改原基本类型变量不会影响List中的元素
- 若需要添加对象后和原对象完全隔离,需要自行实现对象的深拷贝逻辑,比如数组可以用
list.add(Arrays.copyOf(element, element.length))实现隔离
内容的提问来源于stack exchange,提问作者Anurag
相关产品推荐
相关产品推荐

