首页 技术 正文
技术 2022年11月11日
0 收藏 379 点赞 2,946 浏览 2256 个字

为什么要复制对象?假设有个类Car,包含name,color2个属性,那么将car1对象复制给car2对象,只需要car2.setName(car1.getName)与car2.setColor(car1.getColor)两部操作即可。

实际项目中有很多类都有超过几十个,甚至上百个字段,这时如果采用以上方式,将会有很大的代码工作量与重复劳动。解决方法是使用反射机制。

首先有2个类如下

 /**
* Created by yesiming on 16-11-19.
*/
public class Car {
private String name;
private String color;
// 省略set/get
}
}
 /**
* Created by yesiming on 16-11-20.
*/
public class Kia extends Car{
private String model;
// 省略set/get
}

我们先操作入职Kia的域

 /**
* 通过反射进行对象复制(漏洞:不能复制父类中的域)
* @throws Exception
*/
@Test
public void copyObject() throws Exception{
User src = new User(); // 源对象
src.setId(1);
src.setName("yesiming");
User target = new User(); // 目标对象
Class clazz = User.class;
Field[] fields = clazz.getDeclaredFields(); // 得到该类声明的域(不包含父类的域)
for(Field field : fields) {
if(!field.isAccessible())
field.setAccessible(true); // 设置可访问
field.set(target, field.get(src)); // 从源对象get值set到目标对象
}
// 输出显示
for(Field field : fields) {
System.out.println(field.get(target));
}
}

由于getDeclaredFields方法不能得到超类中的域,所以上述操作有缺陷,甚至不具有实际意义

下面是如何得到超类中的域,使用递归即可

 /**
* 输出所有域,包括父类中的域(通过递归实现)
*/
public void showAllField(Class clazz) {
Field[] fields = clazz.getDeclaredFields();
System.out.println("------" + clazz.toString() + "------");
if(fields != null && fields.length > 0) {
for(Field field : fields) {
System.out.println(field);
}
}
Class superClazz = clazz.getSuperclass();
if(superClazz != Object.class) { // 结束递归
showAllField(superClazz); // 递归
}
} @Test
public void showAllFieldTest() {
Class clazz = Kia.class;
showAllField(clazz);
}

运行结果如下:

------class o1.o1_a.Kia------
private java.lang.String o1.o1_a.Kia.model
------class o1.o1_a.Car------
private java.lang.String o1.o1_a.Car.name
private java.lang.String o1.o1_a.Car.color

那么好,结合上述2种操作,就能写出具有实用价值的类复制方法了吗?

当然不是,Java中操作Bean的专业户是内省,Introspector

 /**
* 通过专业操作JavaBean的内省,Introspector复制有继承的类
* @throws Exception
*/
@Test
public void showProfile() throws Exception { Kia k1 = new Kia(); // 源对象,继承自Car
k1.setName("起亚"); // 这是Car中的域
k1.setColor("白色"); // 这是Car中的域
k1.setModel("K4");
Kia k2 = new Kia(); // 目标对象 BeanInfo beanInfo = Introspector.getBeanInfo(Kia.class); // 得到Kia的Bean信息
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); //通过BeanInfo得到域的描述符
for (PropertyDescriptor pd : pds) {
if (pd.getName() == "getClass()") {
continue;
}
if (pd.getReadMethod() == null || pd.getWriteMethod() == null) { // 如果set, get不配对就不复制
continue;
}
// 反射set目标对象中的域
pd.getWriteMethod().invoke(k2, pd.getReadMethod().invoke(k1));
}
System.out.println(k2.getName() + k2.getModel() + k2.getColor());
}
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,087
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,562
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,412
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,185
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,821
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,905