拷贝的基本含义
拷贝,也就是复制的意思。
体现在电脑里,也就是说在存储中产生一个与原对象相同的复制对象。
Java中与复制相关的一些规则
在java中拷贝是无处不在的。比如说,传参,返回值,赋值等等。
java出于效率的考虑,会 区分对待基本数据类型(int,double…),以及对象的拷贝。
注意:
- 对于基本数据类型的拷贝代价是比较小的,所以可以直接复制值。
- 对于对象的复制,代价可能是很大的,所以基于简单的原则,java一般情况下只是复制其引用。【基本的一个原则】
java拷贝的代码实例
(1)使用clone.
1- java 还是考虑到了用户在复制方面的需求,所以通过clone方法,来供用户实现自己的需求。
2- java默认实现的clone方法,是不完全的拷贝(浅拷贝),它拷贝的效果,是为新生成的对象重新分配内存空间,并且对于基本的数据类型进行复制。 然而,对于被复制对象内部的对象,则是仅仅复制了其内部包含的对象的引用。 【这是符合前面说的“简单原则”的】
下面是与之相关的实例代码:
public class CopyTestClass {
public static void main(String[] args) throws CloneNotSupportedException {
//1.创建一个对象first,并且给其成员变量赋值。
Position first = new Position(1, 1, 1);
first.layerAndBranch.put(55, 66);
System.out.println(first.toString());
//2.使用复制方法,并且将复制结果 给了引用 second.
Position second = (Position) first.clone();
//3.在second对象中,对成员变量进行修改。
// 3.1.更改second中的基本类型。
second.layer = 2;
// 3.2.更改second中的map。
second.layerAndBranch.put(55, 0);
//4.输出结果。
System.out.println(first.toString());
System.out.println(second.toString());
}
//position 定义为了静态内部类。(实现clone方法)
public static class Position implements Cloneable{
public int layer;
public int currentBranch;
public int positionInBranch;
public Map<Integer, Integer> layerAndBranch = new HashMap<Integer, Integer>();
Position(int layer, int branch, int positionInBranch) {
this.layer = layer;
this.currentBranch = branch;
this.positionInBranch = positionInBranch;
}
//重写了方法,便于观察。
@Override
public String toString() {
return "[" + super.toString() + "]\n" + layer + "-" + currentBranch + "-" + positionInBranch +"\n"
+ "map: " + 55 + " ---> " +layerAndBranch.get(55);
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
}
输出结果:
- 复制之后,对象的id是不一样的了,说明新生成了一个对象。
- 修改复制对象(second)的基本类型(int)后,并不影响原对象的与之相关的成员。
- 修改复制对象(second)的对象成员(map)后,对原对象造成了影响。
[javaTest.refTest.CopyTestClass$Position@a62812d]
1-1-1
map: 55 ---> 66
[javaTest.refTest.CopyTestClass$Position@a62812d]
1-1-1
map: 55 ---> 0
[javaTest.refTest.CopyTestClass$Position@490eb6ae]
2-1-1
map: 55 ---> 0
(2)使用序列化(Serializable)
该对象序列化成流,流中的对象是 虚拟机中对象的一个完整的拷贝。(包括:基本类型,其他成员对象)
代码实例:
public class CopyDeepTest {
public static void main(String[] args) throws Exception {
Position first = new Position(1, 1, 1);
first.layerAndBranch.put(55, 66);
System.out.println(first.toString());
Position second = (Position) first.deepCopy();
second.layer = 2;
second.layerAndBranch.put(55, 0);
System.out.println(first.toString());
System.out.println(second.toString());
}
public static class Position implements Serializable {
public int layer;
public int currentBranch;
public int positionInBranch;
public Map<Integer, Integer> layerAndBranch = new HashMap<Integer, Integer>();
Position(int layer, int branch, int positionInBranch) {
this.layer = layer;
this.currentBranch = branch;
this.positionInBranch = positionInBranch;
}
@Override
public String toString() {
return "[" + super.toString() + "]\n" + layer + "-" + currentBranch + "-" + positionInBranch + "\n"
+ "map: " + 55 + " ---> " + layerAndBranch.get(55);
}
public Object deepCopy() throws Exception {
// 该对象序列化成流,流中的对象是 虚拟机中对象的一个完整的拷贝。(包括:基本类型,其他成员对象)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 流转化为对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
}
输出结果:
- 两个对象(源对象,复制对象)中都各有一个独立的map对象。
[javaTest.refTest.CopyDeepTest$Position@6208f57a]
1-1-1
map: 55 ---> 66
[javaTest.refTest.CopyDeepTest$Position@6208f57a]
1-1-1
map: 55 ---> 66
[javaTest.refTest.CopyDeepTest$Position@10d13e3e]
2-1-1
map: 55 ---> 0