循环内创建对象还是循环外创建对象,以及集合中存储对象的引用问题
在日常开发中经常会使用集合存储大量对象,所以会在每次循环时创建一个对象然后存入集合中,这样创建大量对象会消耗很多内存,于是就想到能不能将创建对象的代码提取出来,节省内存:
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<>();
for (int i = 0; i < 3; i++) {
Student student = new Student();
student.setUsername("zhangsan"+i);
student.setAge(i);
list.add(student);
}
System.out.println(list);
}
将创建对象代码提取出来后:
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<>();
Student student = new Student();
for (int i = 0; i < 3; i++) {
student.setUsername("zhangsan"+i);
student.setAge(i);
list.add(student);
}
System.out.println(list);
}
但输出时就发现了问题,发现其中的都是同一个对象;
因为list集合中一直保存的都是同一个对象的引用student,后续的赋值操作一直改变的都是该对象的内容,所以最后list集合中保存的是同一个对象最后赋值时的内容:
[Student{username='zhangsan2', age=2}, Student{username='zhangsan2', age=2}, Student{username='zhangsan2', age=2}]
再打印内存地址:
[com.mydemo.pojo.Student@1f32e575, com.mydemo.pojo.Student@1f32e575, com.mydemo.pojo.Student@1f32e575]
本来以为这是很简单的问题就这样结束了,看到这一段代码又迷茫了:
public static void main(String[] args) {
ArrayList<Object> list = new ArrayList<>();
Student student = null;
for (int i = 0; i < 3; i++) {
Student stu = new Student();
stu.setUsername("zhangsan"+i);
stu.setAge(i);
student = stu;
list.add(student);
}
System.out.println(list);
}
打印的是正确结果:
[Student{username='zhangsan0', age=0}, Student{username='zhangsan1', age=1}, Student{username='zhangsan2', age=2}]
按道理,list集合中保存的数据也全部是同一个引用啊,但是打印结果却表示是不同的对象引用;
后来研究了一下集合保存对象的方式才慢慢明白:
集合保存对象时,保存的是对象的引用,也就是保存的是对象的地址,当上述中的student指向一个对象并且存入list集合中时,此时集合中第一位保存的是该对象的内存地址,student又指向另一个对象时,list集合中第二位保存的时另一个对象的内存地址,以此类推所以list中保存的是不同的对象;
所以使用list集合保存对象时是避免不了创建大量对象的;