向ArrayList中添加Java对象出现结果异常的问题咨询
问题原因分析与解决办法
这是个很典型的Java对象引用问题,核心原因其实特别直观:你从头到尾只创建了一个Classname对象实例,两次往ArrayList里添加的都是同一个对象的引用。
具体拆解一下逻辑:
- 当你执行
Classname cl = new Classname();时,JVM会在堆内存里生成一个Classname对象,变量cl保存的是这个对象的内存地址(也就是引用)。 - 第一次调用
yourList.add(cl)后,列表的第0个元素指向的就是这个堆里的对象。 - 之后你修改
cl.Name和cl.Age,本质上是在修改堆内存中那个唯一的Classname对象的属性值,并没有创建新对象。 - 第二次调用
yourList.add(cl)时,只是把同一个对象的引用再次添加到列表的第1个位置而已。
所以当你打印列表元素时,两个位置的元素指向的都是堆里的同一个对象,自然显示的都是最后修改的john和20。
修正方案
要得到你预期的结果,需要为每个要添加到列表的元素创建独立的Classname实例,同时还要注意内部类的静态问题(非静态内部类不能在静态的main方法中直接实例化),修正后的代码如下:
public class main { public static void main(String[] args) throws Exception { ArrayList<Classname> yourList = new ArrayList<Classname>(); // 创建第一个独立实例 Classname cl1 = new Classname(); cl1.Name = "paul"; cl1.Age = 30; yourList.add(cl1); // 创建第二个独立实例 Classname cl2 = new Classname(); cl2.Name = "john"; cl2.Age = 20; yourList.add(cl2); System.out.println("List row 0 = "+yourList.get(0).Name+" - "+yourList.get(0).Age); System.out.println("List row 1 = "+yourList.get(1).Name+" - "+yourList.get(1).Age); } // 将内部类改为静态,允许在main方法中直接实例化 static class Classname{ public String Name; public Integer Age; } }
运行这段代码后,就能得到你预期的row(0) = (paul,30)、row(1) = (john,20)结果了。
内容的提问来源于stack exchange,提问作者Diego Retaggi
相关产品推荐
相关产品推荐

