List的clone()⽅法
概述
在查看ArrayList和LinkedList的源码的时候,⽐较困惑的就是clone()⽅法。
我们都知道在Object⾥clone()⽅法是浅拷贝(浅拷贝的定义:只clone对象本⾝,不clone对象⾥的字段),那在集合⾥它到底是深拷贝还是浅拷贝呢?
我们看⼀下ArrayList.clone()源码:
public Object clone() {
try {
@SuppressWarnings("unchecked")
ArrayList<E> v = (ArrayList<E>) super.clone();
v.elementData = pyOf(elementData, size);
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError();
}
}
我们可以看到,返回的是⼀个全新的ArrayList实例对象,但是其elementData,也就是存储数据的数组,存储的对象还是指向了旧的ArrayList存储的那些对象。也就是ArrayList这个类实现了深拷贝,但是存储的对象还是浅拷贝。
我们验证⼀下:
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
static Main ins = new Main();
//内部类
class Node{
int val;
Node(int val){
this.val = val;
}
public void setVal(int val) {
this.val = val;
}
@Override
public String toString() {
return"Node [val=" + val + "]";
}
}
public static void main(String[] args) {
ArrayList<Node> list = new ArrayList<Node>();
list.w Node(2));
list.w Node(11));
list.w Node(44));
ArrayList<Node> newlist = (ArrayList<Node>) list.clone();
/
/修改list中元素之前的newlist
for(Node k : newlist){
System.out.println(k);
}
//修改list中index为0的对象的值为90
<(0).setVal(90);
System.out.println("--------------------------------");
//修改后newlist,index为0的对象也变化了
for(Node k : newlist){
System.out.println(k);
}
}
}
其运⾏结果为:
Node [val=2]
Node [val=11]
Node [val=44]
--------------------------------
Node [val=90]
Node [val=11]
Node [val=44]
我们可以看到,通过改变旧的list存储的对象的值,新的list存储的对象的值也发⽣了改变。说明其指向了同⼀个对象。
那么会不会list和newlist其实指向同⼀个对象呢?
执⾏System.out.println("list==newlist?:"+(list==newlist));
其结果为:list==newlist?:false
说明list和newlist指向两个不同的内存地址空间
同样的,LinkedList的clone()也是实现⼀个浅复制
1011/**
1012      * ⽗类克隆⽅法
1013      */
1014@SuppressWarnings("unchecked")
1015private LinkedList<E> superClone() {
1016try {
1017return (LinkedList<E>) super.clone();
1018        } catch (CloneNotSupportedException e) {
1019throw new InternalError(e);
1020        }
1021    }
1022
1023/**
1024      * 克隆,浅拷贝
1025      *
1026      * @return a shallow copy of this {@code LinkedList} instance
1027      */
1028public Object clone() {
1029        LinkedList<E> clone = superClone();
1030
1031// 链表初始化
1032        clone.first = clone.last = null;
1033        clone.size = 0;
1034        dCount = 0;
1035
1036// 插⼊结点
1037for (Node<E> x = first; x != null; x = x.next)
1038            clone.add(x.item);
1039// 返回克隆后的对象引⽤
1040return clone;
1041    }
那么要怎么实现⼀个ArrayList的深拷贝呢?
通过实现对象类的clone⽅法。
import java.util.ArrayList;
import java.util.Iterator;
public class Main {
static Main ins = new Main();
class Node{
int val;
Node(int val){
this.val = val;
}
public void setVal(int val) {
this.val = val;
}
@Override
public String toString() {
return"Node [val=" + val + "]";
}
//在对象中重写clone()⽅法
@Override
public Node clone(){
Node node = new Node(this.val);
return node;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayList<Node> list = new ArrayList<Node>();
list.w Node(2));
list.w Node(11));
list.w Node(44));
//深拷贝
ArrayList<Node> listCopy = new ArrayList<>();
for(Node node:list){
listCopy.add(node.clone());
}
//移除且不修改
<(0).setVal(100);
System.out.println(list);
System.out.println(listCopy);
}
}
结果为:
[Node [val=2], Node [val=11], Node [val=44]]
clone[Node [val=100], Node [val=11], Node [val=44]]

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。