Java将一个List赋值给另一个List的问题

       最近在写代码的时候发现一个问题:我定义了两个List集合A,B,先对第一个集合A add数据进去,接着直接将A的数据赋值给B,结果后面我将集合A给clear掉,然后使用B集合的数据,结果报了数组越界异常。

最后发现集合B的数据也不存在了。测试代码如下:

List<String> A =new ArrayList<>();
List<String> B =new ArrayList<>();

 A.add("111");
 A.add("222");
 A.add("333");

 B=A;
 System.out.println("A:"+A);
 System.out.println("B:"+B);

 A.clear();
        
 System.out.println("A:"+A);
 System.out.println("B:"+B);

输出结果为:

A:[111, 222, 333]
B:[111, 222, 333]
A:[]
B:[]

 看到这个结果我纳闷了好久,我明明没有将集合B的数据给删掉,只删除了A的数据,为什么B的数据也没了。于是我猜测:

在用B=A 这个方式对集合B进行复制时将集合A对应的地址赋给了集合B,并不是单纯的将集合A的数据赋给集合B。在对A进行clear操作时将A对应的存储空间也就是地址给删除了,那么存储空间里的数据也就随之删除了。而B指向的地址又是A对应的地址,那么B里面的数据也就没有了。

为了印证我的猜测,我查找相关资料后得知:

Java中 "="的作用有两个:

1.赋值

2.指向地址

那么这两个作用具体什么情况下起什么作用呢?答案如下:

扫描二维码关注公众号,回复: 9905140 查看本文章

当对基本数据类型进行赋值时 "="的作用就是单纯的赋值,例如:int i=1,int j=2;

而当对引用数据类型进行赋值时"="的作用就是将被赋值对象的地址指向赋值对象的地址,例如:

List<String> A =new ArrayList<>();
List<String> B =new ArrayList<>();
A=B;

这里插入讲一下Java堆、栈、常量池的区别:

栈:一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,但对象本身不存放在栈中,而是存放在堆(new出来的对象)或者常量池中(对象可能在常量池里)(字符串常量对象存放在常量池中。)
堆:存放new 出来的对象。
常量池:存放字符串常量和基本类型常量(public static final)。

对于栈和常量池中的对象可以共享,对于堆中的对象不可以共享。

注意看上面对栈的描述,当我们定义两个List集合A,B的时候,集合A,B是引用数据类型,那么他们的引用先是在栈内存中分配,而对象本身是在进行new操作的时候存放在堆内存中,由堆进行内存分配。所以我们用B=A这种方式对集合B进行赋值时其实是将A的引用赋值给B,也就是说B指向了A的地址。当对A或是对B进行数据clear,add等操作时相应的B或A中的数据也会发生对应的变化。

最后,如果要将一个List集合赋值给另一个List集合,并且操作其中一个集合不会影响另一个集合时,可以用以下几种方法:

//方法一
ArrayList B = new ArrayList<> (A);

//方法二
B.addAll(A);

//方法三
B = A.clone();

//方法四
for(String s: A)
 B.add(s);

此次出现的问题纠结了我好久,其实也都是很基础的问题,但平时不怎么注意,导致浪费大量时间找寻bug。所以一定要注重基础啊。

特在此记录以下!

发布了16 篇原创文章 · 获赞 30 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/zcczero/article/details/103632869
今日推荐