被声明为final的ArrayList扩容时为何能正常工作?原理解析
关于final修饰ArrayList后扩容仍能正常工作的原因
先看你给出的代码:
final ArrayList<Integer> list = new ArrayList<>();
你之前的描述存在一个关键误解:ArrayList扩容时,并没有让list引用指向新的ArrayList对象,这也是问题的核心所在。下面拆解背后的逻辑:
final修饰引用变量的本质
用final修饰list这个引用变量时,它只限制一件事:list这个变量本身不能被重新赋值,指向其他ArrayList对象。但它完全不限制我们修改list所指向的那个ArrayList对象的内部状态——比如添加/删除元素、修改内部存储数组等操作都是允许的。ArrayList扩容的真实过程
ArrayList内部靠一个名为elementData的数组来存储元素。当添加第11个元素时,原数组容量(默认10)不够用了,它会执行以下步骤:
- 创建一个新的容量为15的数组;
- 将原数组里的10个元素复制到新数组中;
- 更新原ArrayList对象内部的
elementData引用,让它指向这个新数组; - 把第11个元素添加到新数组里。
整个过程中,list这个引用始终指向最初创建的那个ArrayList对象,从来没有被重新赋值过,完全符合final的约束。旧的数组会被垃圾回收,但旧的ArrayList对象本身并没有被替换,只是它内部的数组被更新了。
所以结论很明确:final限制的是引用变量的指向,而非对象的内部状态,因此ArrayList的扩容操作可以正常执行。
内容的提问来源于stack exchange,提问作者Debasish Biswas
相关产品推荐
相关产品推荐

