java拷贝分为两种:引用拷贝和对象拷贝
引用拷贝:不需要申请堆内存,只是将拷贝后的的引用指向原来的对象;
对象拷贝:需要申请堆内存,是一个新的对象;(对象拷贝分为深拷贝和浅拷贝),下面予以说明。
1.准备工作。
类:
public class Address implements Serializable{
}
public class User implements Cloneable,Serializable{
private Address address;
public void setAddress(Address address) {
this.address = address;
}
public Address getAddress() {
return address;
}
@Override
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
//利用串行化来实现深拷贝
public Object deepClone()throws Exception{
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
oos.flush();
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
解释:ByteArrayOutputStream类是在创建它的实例时,程序内部创建一个byte型别数组的缓冲区,然后利用ByteArrayOutputStream和ByteArrayInputStream的实例向数组中写入或读出byte型数据。在网络传输中我们往往要传输很多变量,我们可以利用ByteArrayOutputStream把所有的变量收集到一起,然后一次性把数据发送出去。
测试类:
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
User user = new User();
Address address = new Address();
user.setAddress(address);
try {
//User user1 =(User) user.clone();//测试浅拷贝
User user1 = (User)user.deepClone();//测试深拷贝
System.out.println(user==user1);
System.out.println(user.getAddress()==user1.getAddress());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
如果仍疑惑可以看下面的升级版
升级:
public class Address implements Serializable{
int a ;
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
}
测试类:
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
User user = new User();
Address address = new Address();
String name = "avc";
user.setAddress(address);
user.setName(name);
try {
//User user1 =(User) user.clone();//测试浅拷贝
User user1 = (User)user.deepClone();//测试深拷贝
System.out.println(user==user1);
System.out.println(user.getAddress()==user1.getAddress());
user.getAddress().setA(4);
System.out.println(user==user1);
System.out.println(user1.getAddress().getA());//修改user的引用对象之后,查看user1的引用对象是否发生修改,判断address是否仍指向同一对象,来区分是浅拷贝还深拷贝。
System.out.println(user.getAddress()==user1.getAddress());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
备注:clone方法的浅拷贝特性主要体现在拷贝对象中含有对象和数组的情况,只是拷贝了引用。
参考:
http://blog.youkuaiyun.com/u014727260/article/details/55003402
http://blog.youkuaiyun.com/chjttony/article/details/7477346