You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么向ArrayList.add()传入同一对象引用时所有元素均为最后一次的值?

问题核心原因:Java的对象引用传递机制

首先要明确Java的核心规则:除了int、char等基础数据类型,所有对象类型的变量存储的都不是对象本身,而是对象在堆内存中的内存地址,也就是常说的「引用」。

原写法的问题拆解

你在for循环外仅执行了一次MyClass obj= new MyClass();,意味着整个程序运行周期里,堆内存中只有1个MyClass实例对象,obj变量永远指向这一个对象的地址:

  • 每次循环修改obj.name/obj.surname/obj.age,都是修改堆内存里这唯一对象的属性值
  • 执行arrayData.add(obj)时,只是把这同一个对象的地址存到ArrayList中,循环5次后ArrayList里的5个元素,全部指向堆内存里的同一个对象
  • 最后一次循环会把这个对象的属性覆盖为最后一次录入的值,自然你从ArrayList里取任意元素,读到的都是这同一个对象的最新属性,所以所有元素展示的都是最后一次录入的数据。

修改后写法的底层差异

你改为arrayData.add(new MyClass(obj.name, obj.surname, obj.age));后,每次执行add都会触发new MyClass(),也就是每次都会在堆内存中创建一个全新的独立MyClass实例:

  • 新对象的属性是从当前obj指向的对象中复制过来的,和原有obj指向的对象没有关联
  • 每次add的是新对象的地址,ArrayList里的5个元素各自指向不同的堆内存对象,互相的属性修改不会产生干扰,自然就能正确存储每次录入的数据。

更易读的优化写法

你完全可以把obj的声明放到循环内部,逻辑更清晰,效果和修改后的写法完全一致:

for (int i=1;i<=5;i++) {
    MyClass obj = new MyClass(); // 每次循环都创建新对象
    System.out.println("-------------------------------------------------------------------------------------");
    System.out.println("Data of person No "+i+" : ");
    System.out.println("Name: ");
    obj.name = input.nextLine();
    System.out.println("Surname: ");
    obj.surname = input.nextLine();
    System.out.println("Age: ");
    obj.age = input.nextInt();
    input.nextLine();
    arrayData.add(obj);
}

内容的提问来源于stack exchange,提问作者Ramzi Bouali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 05:09:00