java 克隆和反射区别_反射实现java深度克隆

一、克隆

有时想得到对象的一个复制品,该复制品的实体是原对象实体的克隆。复制品实体的变化不会引起原对象实体发生变化,这样的复制品称为原对象实体的克隆对象或简称克隆。

1、浅复制(浅克隆)

概念:被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

方法:类implements Cloneable,然后重写clone()方法,在clone()方法中调用super.clone()即可,没有其他操作了

2、深复制(深克隆)

概念:被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

一、克隆的实现

1、通过java的序列化实现克隆,即先对原对象进行序列化,然后再反序列化得到目标对象。

2. 通过反射进行,通过反射,获取对象的内部数据域,然后将数据依次复制,不多说,先上代码

package Reflection;

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;

public class DeepCloneUtil {

public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException, InstantiationException {

Person p = new Person("zhanchi",26);

System.out.println(Person.num);

Person p2 = (Person) cloneObject(p);

System.out.println(p2.getName());

System.out.println(p2.getAge());

System.out.println(p.list == p2.list);

System.out.println(p2.list.get(0) == p2);

System.out.println(p.list.get(0) == p2);

System.out.println(Person.num);

}

/**

* 返回对象的所以属性 包括继承至父类的属性

* @param o

* @return

*/

private static List getAllFieads(Object o) {

List fields = new ArrayList();

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 map = new HashMap();

return cloneObject(o,map);

}

private static Object cloneObject(Object o, Map 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 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 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 map) throws SecurityException,

IllegalArgumentException, IllegalAccessException,

InstantiationException {

if(null == object || null == newObject){

return ;

}

List 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));

}

}

}

}

class Person{

static int num = 0;

Person p;

final List list = new ArrayList();

String [] testString = new String[3];

public Person() {

num ++ ;

}

public Person(String name, int age) {

this.age=age;

this.name=name;

p = this;

testString[2] = name;

list.add(p);

list.add(new Person());

num ++ ;

}

public String getName() {

return name;

}

public int getAge() {

return age;

}

@Override

public String toString(){

return "["+this.name+"  "+this.age+"]";

}

private String name;

private int age;

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值