浅克隆:顾名思义就是很表面的很表层的克隆,比如我们要克隆User对象,浅克隆只克隆他自身以及他包含的所有对象的引用地址。 深克隆:就是非浅克隆。克隆除自身以外所有的对象,包括自身所包含的所有对象实例。至于深克隆的层次,由具体的需求决定,也有“N层克隆”一说。
浅克隆: 1、使用Cloneable接口实现,步骤如下: a. 让该类实现Java.lang.Cloneable接口; b. 重写(override)Object类的clone()方法。
深克隆: 方法1:通过Cloneable接口实现,但这里必须类中所有的非基本类型域都实现Cloneable接口,才能实现深克隆,所以此方法不通用 方法2:通过串行化方式实现(克隆对象必须实现Serializable接口) 把对象写到流里的过程是串行化(Serilization)过程,但是在Java程序师圈子里又非常形象地称为“冷冻”或者“腌咸菜(picking)”过程;而把对象从流中读出来的并行化(Deserialization)过程则叫做 “解冻”或者“回鲜(depicking)”过程。 应当指出的是,写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面,因此“腌成咸菜”的只是对象的一个拷贝,Java咸菜还可以回鲜。 在Java语言里深复制一个对象,常常可以先使对象实现Serializable接口,然后把对象(实际上只是对象的一个拷贝)写到一个流里(腌成咸菜),再从流里读出来(把咸菜回鲜),便可以重建对象。
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public abstract class BeanUtil { @SuppressWarnings("unchecked") public static <T> T cloneTo(T src) throws RuntimeException { ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream(); ObjectOutputStream out = null; ObjectInputStream in = null; T dist = null; try { out = new ObjectOutputStream(memoryBuffer); out.writeObject(src); out.flush(); in = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray())); dist = (T) in.readObject(); } catch (Exception e) { throw new RuntimeException(e); } finally { if (out != null) try { out.close(); out = null; } catch (IOException e) { throw new RuntimeException(e); } if (in != null) try { in.close(); in = null; } catch (IOException e) { throw new RuntimeException(e); } } return dist; } }方法3:通过反射的方式实现(克隆对象必须是可序列化的) 即依次遍历克隆对象中的所有域,直至全部域均为基本类型为止
package com.example.xiaowang.clonetest; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * Created by xiaowang on 17/3/9. */ public class CloneUtil { /** * 返回对象的所以属性 包括继承至父类的属性 * * @param o * @return */ private static List<Field> getAllFieads(Object o) { List<Field> fields = new ArrayList<Field>(); if (null == o) { return fields; } Class<?> type = o.getClass(); do { for (Field f : type.getDeclaredFields()) { fields.add(f); } type = type.getSuperclass(); } while (null != type); return fields; } /** * 基于效率的考虑不需要进行深度复制的类型:包括基本类型和包装类 * * @param o * @return */ public static boolean isSimpleObject(Object o) { Class<?> type = o.getClass(); if (type.isPrimitive()) { // 基本类型 return true; } // 不可更改的变量类型 如 String,Long if (type.equals(String.class)) { return true; } if (type.equals(Long.class)) { return true; } if (type.equals(Boolean.class)) { return true; } if (type.equals(Short.class)) { return true; } if (type.equals(Integer.class)) { return true; } if (type.equals(Character.class)) { return true; } if (type.equals(Float.class)) { return true; } if (type.equals(Double.class)) { return true; } if (type.equals(Byte.class)) { return true; } return false; } /** * 没有对cloneAble接口进行限制 * * @param o * @return * @throws IllegalArgumentException * @throws IllegalAccessException * @throws InstantiationException */ public static Object cloneObject(Object o) throws IllegalArgumentException, IllegalAccessException, InstantiationException { if (null == o) { return null; } // 使用Map保存原对象和副本对象之间的结构,防止被多次引用的对象重复重建 Map<Object, Object> map = new HashMap<Object, Object>(); return cloneObject(o, map); } private static Object cloneObject(Object o, Map<Object, Object> map) throws IllegalArgumentException, IllegalAccessException, InstantiationException { if (null == o) { return null; } Object newInstance = null; newInstance = map.get(o); if (null != newInstance) { return newInstance; } if (isSimpleObject(o)) return o; // 数组类型 if (o.getClass().isArray()) { return cloneArray(o, map); } Class<?> type = o.getClass(); newInstance = type.newInstance(); map.put(o, newInstance); cloneFields(o, newInstance, map); return newInstance; } /** * 克隆数组对象 * * @param o * @param map * @return * @throws InstantiationException * @throws IllegalAccessException * @throws IllegalArgumentException */ private static Object cloneArray(Object o, Map<Object, Object> map) throws IllegalArgumentException, IllegalAccessException, InstantiationException { if (null == o) { return null; } if (!o.getClass().isArray()) { return cloneObject(o, map); } int len = Array.getLength(o); Object array = Array.newInstance(o.getClass().getComponentType(), len); map.put(o, array); for (int i = 0; i < len; i++) { Array.set(array, i, cloneObject(Array.get(o, i), map)); } return array; } /** * 对于final类型的变量 如果其为引用, 则尽管引用的值不需要更改,但引用对象的数据还是需要填充的 * * @param object * @param newObject * @param map * @return * @throws IllegalArgumentException * @throws IllegalAccessException * @throws InstantiationException */ private static void cloneFinalObject(Object object, Object newObject, Map<Object, Object> map) throws IllegalArgumentException, IllegalAccessException, InstantiationException { if (object == null || newObject == null || object == newObject || !newObject.getClass().equals(newObject.getClass())) { return; } // 对于final类型的变量 if (null != map.get(newObject)) { return; } map.put(newObject, newObject); cloneFields(object, newObject, map); return; } private static void cloneFields(Object object, Object newObject, Map<Object, Object> map) throws SecurityException, IllegalArgumentException, IllegalAccessException, InstantiationException { if (null == object || null == newObject) { return; } List<Field> fields = getAllFieads(object); for (Field f : fields) { // 静态变量过滤掉 或者final的变量 if (Modifier.isStatic(f.getModifiers())) continue; // 常量 if (Modifier.isFinal(f.getModifiers())) { cloneFinalObject(f.get(object), f.get(newObject), map); } else { f.setAccessible(true); f.set(newObject, cloneObject(f.get(object), map)); } } } }方法4:通过Json转换的方式(克隆对象必须实现Serializable接口)
Bean bean1 = new Bean(); Bean bean2 = new Gson().fromJson(new Gson().toJson(bean1), new TypeToken<Bean>(){}.getType());