为什么要复制对象?假设有个类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());
}

Java反射 - 2(对象复制,父类域,内省)的更多相关文章

  1. Java 反射 Class对象

    Java 反射 Class对象 @author ixenos 关键字:RTTI.动态绑定.动态加载.获得Class引用.泛型Class引用.newInstance的坑.JVM中的泛型类型信息 RTTI ...

  2. 【译】2. Java反射——Class对象

    原文地址:http://tutorials.jenkov.com/java-reflection/classes.html ====================================== ...

  3. Java反射获取对象成员属性,getFields()与getDeclaredFields()方法的区别

    Java反射获取对象成员属性,getFields()与getDeclaredFields()方法的区别 ​ 在工作中遇到一个问题,就是你需要去判断某个字符串是不是对象的某个成员属性名,然后根据判断结果 ...

  4. java 反射,注解,泛型,内省(高级知识点)

     Java反射 1.Java反射是Java被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运行时透过Reflection APIs    取得任何一个已知名称的class的内部信息, 包括 ...

  5. java反射构建对象和方法的反射调用

    Java反射技术应用广泛,其能够配置:类的全限定名,方法和参数,完成对象的初始化,设置是反射某些方法.可以增强java的可配置性. 1.1 通过反射构建对象(无参数): 例如我们使用 ReflectS ...

  6. Java反射获取对象VO的属性值(通过Getter方法)

    有时候,需要动态获取对象的属性值. 比如,给你一个List,要你遍历这个List的对象的属性,而这个List里的对象并不固定.比如,这次User,下次可能是Company. e.g. 这次我需要做一个 ...

  7. 第五课 JAVA反射获取对象属性和方法(通过配置文件)

    Service1.java package reflection; public class Service1 { public void doService1(){ System.out.print ...

  8. 用Java反射输出对象的所有属性的值

    获取对象的类类型 Class cls = obj.getClass(); 用类类型获取属性数组 getFields()获取的是共有属性 getDeclaredFields()可以获取所有属性 Fiel ...

  9. 第五课 JAVA反射获取对象属性和方法

    package com.hero; import java.lang.reflect.Field; public class TestReflction5 { public static void m ...

随机推荐

  1. 常用的JQuery UI框架

    http://www.ligerui.com/ http://www.jeasyui.com/index.php http://www.jqwidgets.com/

  2. 托管host

    托管在googlecode的host https://smarthosts.googlecode.com/svn/trunk/hosts

  3. activitie5 流程入门例子

    流程这个东西在ERP项目用得比较多.在网上找到一个例子,与大家分享一下.http://yiyiboy2010.iteye.com/blog/1530924 感谢原博主提供 http://blog.ch ...

  4. POJ1860 Currency Exchange(最短路)

    题目链接. 分析: 以前没做出来,今天看了一遍题竟然直接A了.出乎意料. 大意是这样,给定不同的金币的编号,以及他们之间的汇率.手续费,求有没有可能通过不断转换而盈利. 直接用Bellman-ford ...

  5. http://aws.amazon.com/cn/ses/ 亚马逊 营销性非事务邮件发送平台

    http://aws.amazon.com/cn/ses/   亚马逊 营销性非事务邮件发送平台

  6. adb shell am pm 用法

    Using activity manager (am) Within an adb shell, you can issue commands with the activity manager (a ...

  7. ANT打包 小实例

    ANT打包 package src; public class Hello { /**   * @param args   */  public static void main(String[] a ...

  8. js中的SetTimeOut

    1. SetTimeOut()              1.1 SetTimeOut()语法例子              1.2 用SetTimeOut()执行Function           ...

  9. 集群中几种session同步解决方案的比较

    1. 客户端cookie加密 .比较好的方法是自己采用cookie机制来实现一个session,在应用中使用此session实现. 问题:session中数据不能太多,最好只有个用户id. Sessi ...

  10. Android SHA1与Package获取方式

    获取应用包名 打开Android 应用工程的 AndroidManifest.xml配置文件,package 属性所对应的内容为应用包名. 如下图所示,红框中的内容: 获取 Sha1 值 开发模式(d ...