欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-01-22 22:26:40
...

       最近在写代码的时候发现一个问题:我定义了两个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.指向地址

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

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

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

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

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

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

栈:一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,但对象本身不存放在栈中,而是存放在堆(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。所以一定要注重基础啊。

特在此记录以下!