JAVA深层拷贝 - DeepCopy

最近需要用到比较两个对象属性的变化,其中一个是oldObj,另外一个是newObj,oldObj是newObj的前一个状态,所以需要在newObj的某个状态时,复制一个一样的对象,由于JAVA不支持深层拷贝,因此专门写了一个方法。


方法实现很简单,提供两种方式:

一种是序列化成数据流,前提是所有对象(对象中包含的对象...)都需要继承Serializable接口,如果都继承了那很容易,如果没有继承,而且也不打算修改所有类,可以用第二种方式。

第二种是将对象序列化为json,通过json来实现拷贝,这种方式需要用到net.sf.json.JSONObject


具体代码如下:

public class DeepCopy {
	/**
	 * 深层拷贝
	 * 
	 * @param <T>
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	public static <T> T copy(T obj) throws Exception {
		//是否实现了序列化接口,即使该类实现了,他拥有的对象未必也有...
		if(Serializable.class.isAssignableFrom(obj.getClass())){
			//如果子类没有继承该接口,这一步会报错
			try {
				return copyImplSerializable(obj);
			} catch (Exception e) {
				//这里不处理,会运行到下面的尝试json
			}
		}
		//如果序列化失败,尝试json序列化方式
		if(hasJson()){
			try {
				return copyByJson(obj);
			} catch (Exception e) {
				//这里不处理,下面返回null
			}
		}
		return null;
	}

	/**
	 * 深层拷贝 - 需要类继承序列化接口
	 * @param <T>
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <T> T copyImplSerializable(T obj) throws Exception {
		ByteArrayOutputStream baos = null;
		ObjectOutputStream oos = null;
		
		ByteArrayInputStream bais = null;
		ObjectInputStream ois = null;
		
		Object o = null;
		//如果子类没有继承该接口,这一步会报错
		try {
			baos = new ByteArrayOutputStream();
			oos = new ObjectOutputStream(baos);
			oos.writeObject(obj);
			bais = new ByteArrayInputStream(baos.toByteArray());
			ois = new ObjectInputStream(bais);

			o = ois.readObject();
			return (T) o;
		} catch (Exception e) {
			throw new Exception("对象中包含没有继承序列化的对象");
		} finally{
			try {
				baos.close();
				oos.close();
				bais.close();
				ois.close();
			} catch (Exception e2) {
				//这里报错不需要处理
			}
		}
	}
	
	/**
	 * 是否可以使用json
	 * @return
	 */
	private static boolean hasJson(){
		try {
			Class.forName("net.sf.json.JSONObject");
			return true;
		} catch (Exception e) {
			return false;
		}
	}
	
	/**
	 * 深层拷贝 - 需要net.sf.json.JSONObject
	 * @param <T>
	 * @param obj
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <T> T copyByJson(T obj) throws Exception {
		return (T)JSONObject.toBean(JSONObject.fromObject(obj),obj.getClass());
	}
}

只需要调用copy方法就行。



  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
Java中的对象赋值和拷贝有两种方式:深拷贝和浅拷贝。 浅拷贝是指,仅仅拷贝对象的引用,而不是对象本身。也就是说,对于原始对象和拷贝对象来说,它们共享同一个内存地址,因此它们的改变会互相影响。 深拷贝是指,拷贝对象本身的所有内容,包括对象中的引用类型。也就是说,对于原始对象和拷贝对象来说,它们有着不同的内存地址,它们的改变不会互相影响。 Java中的浅拷贝可以使用Object类的clone()方法实现,而深拷贝需要自己实现。下面是一个深拷贝的例子: ```java import java.io.*; public class DeepCopy implements Serializable { private String name; private int age; private Person person; public DeepCopy(String name, int age, Person person) { this.name = name; this.age = age; this.person = person; } public DeepCopy deepCopy() throws IOException, ClassNotFoundException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return (DeepCopy) ois.readObject(); } public static void main(String[] args) { Person person = new Person("Tom"); DeepCopy original = new DeepCopy("David", 20, person); try { DeepCopy copy = original.deepCopy(); System.out.println("original == copy? " + (original == copy)); // false System.out.println("original.person == copy.person? " + (original.person == copy.person)); // false } catch (Exception e) { e.printStackTrace(); } } } class Person implements Serializable { private String name; public Person(String name) { this.name = name; } } ``` 在这个例子中,DeepCopy类包含了一个Person类的引用类型。在deepCopy()方法中,我们将对象序列化成字节流,然后再将字节流反序列化成对象,这样就实现了深拷贝。在main()方法中,我们分别创建了原始对象和拷贝对象,并且打印了它们的地址和对象中引用类型的地址,可以看到它们都是不同的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

isea533

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值