java 同名对象_java不同对象之间同名属性值复制

1. 利用apache commons-beanutils的开源实现

BeanUtils.copyProperties(dst, src)。方法能够将源对象和目标对象中相同名称的属性值复制过去。注意的是参数前面的是目标对象,后面是源对象。使用该方法需要注意:不能将入口方法与源对象、目标对象之一放在同一源文件之内,否者将没有任何效果。

使用该方法,代码简洁,但是底层利用反射机制,还有许多校验,性能不是十分好。

2.利用ReflectASM,自己编写copyProperties方法

ReflectASM,高性能的反射:

什么是ReflectASM    ReflectASM是一个很小的java类库,主要是通过asm生产类来实现java反射,执行速度非常快,看了网上很多和反射的对比,觉得ReflectASM比较神奇,很想知道其原理,下面介绍下如何使用及原理;

publicstaticvoidmain(String[] args) {

User user = newUser();

//使用reflectasm生产User访问类

MethodAccess access = MethodAccess.get(User.class);

//invoke setName方法name值

access.invoke(user, "setName","张三");

//invoke getName方法 获得值

String name = (String)access.invoke(user, "getName",null);

System.out.println(name);

}

原理

上面代码的确实现反射的功能,代码主要的核心是 MethodAccess.get(User.class);

看了下源码,这段代码主要是通过asm生产一个User的处理类 UserMethodAccess(这个类主要是实现了invoke方法)的ByteCode,然后获得该对象,通过上面的invoke操作user类。

ASM反射转换:

privatestaticMap methodMap =newHashMap();

privatestaticMap methodIndexMap =newHashMap();

privatestaticMap> fieldMap =newHashMap>();

publicstaticvoidcopyProperties(Object desc, Object orgi) {

MethodAccess descMethodAccess = methodMap.get(desc.getClass());

if(descMethodAccess ==null) {

descMethodAccess = cache(desc);

}

MethodAccess orgiMethodAccess = methodMap.get(orgi.getClass());

if(orgiMethodAccess ==null) {

orgiMethodAccess = cache(orgi);

}

List fieldList = fieldMap.get(orgi.getClass());

for(String field : fieldList) {

String getKey = orgi.getClass().getName() + "."+"get"+ field;

String setkey = desc.getClass().getName() + "."+"set"+ field;

Integer setIndex = methodIndexMap.get(setkey);

if(setIndex !=null) {

intgetIndex = methodIndexMap.get(getKey);

// 参数一需要反射的对象

// 参数二class.getDeclaredMethods 对应方法的index

// 参数对三象集合

descMethodAccess.invoke(desc, setIndex.intValue(),

orgiMethodAccess.invoke(orgi, getIndex));

}

}

}

// 单例模式

privatestaticMethodAccess cache(Object orgi) {

synchronized(orgi.getClass()) {

MethodAccess methodAccess = MethodAccess.get(orgi.getClass());

Field[] fields = orgi.getClass().getDeclaredFields();

List fieldList = newArrayList(fields.length);

for(Field field : fields) {

if(Modifier.isPrivate(field.getModifiers())

&& !Modifier.isStatic(field.getModifiers())) { // 是否是私有的,是否是静态的

// 非公共私有变量

String fieldName = StringUtils.capitalize(field.getName()); // 获取属性名称

intgetIndex = methodAccess.getIndex("get"+ fieldName);// 获取get方法的下标

intsetIndex = methodAccess.getIndex("set"+ fieldName);// 获取set方法的下标

methodIndexMap.put(orgi.getClass().getName() + "."+"get"

+ fieldName, getIndex); // 将类名get方法名,方法下标注册到map中

methodIndexMap.put(orgi.getClass().getName() + "."+"set"

+ fieldName, setIndex); // 将类名set方法名,方法下标注册到map中

fieldList.add(fieldName); // 将属性名称放入集合里

}

}

fieldMap.put(orgi.getClass(), fieldList); // 将类名,属性名称注册到map中

methodMap.put(orgi.getClass(), methodAccess);

returnmethodAccess;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值