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]
java定义一维数组并赋值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堆、栈、常量池的区别:
栈:⼀些基本类型的变量和对象的引⽤变量都是在函数的栈内存中分配,但对象本⾝不存放在栈中,⽽是存放在堆(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。所以⼀定要注重基础啊。
特在此记录以下!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论