Java反射 - 2(对象复制,父类域,内省)
为什么要复制对象?假设有个类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(对象复制,父类域,内省)的更多相关文章
- Java 反射 Class对象
Java 反射 Class对象 @author ixenos 关键字:RTTI.动态绑定.动态加载.获得Class引用.泛型Class引用.newInstance的坑.JVM中的泛型类型信息 RTTI ...
- 【译】2. Java反射——Class对象
原文地址:http://tutorials.jenkov.com/java-reflection/classes.html ====================================== ...
- Java反射获取对象成员属性,getFields()与getDeclaredFields()方法的区别
Java反射获取对象成员属性,getFields()与getDeclaredFields()方法的区别 在工作中遇到一个问题,就是你需要去判断某个字符串是不是对象的某个成员属性名,然后根据判断结果 ...
- java 反射,注解,泛型,内省(高级知识点)
Java反射 1.Java反射是Java被视为动态(或准动态)语言的一个关键性质.这个机制允许程序在运行时透过Reflection APIs 取得任何一个已知名称的class的内部信息, 包括 ...
- java反射构建对象和方法的反射调用
Java反射技术应用广泛,其能够配置:类的全限定名,方法和参数,完成对象的初始化,设置是反射某些方法.可以增强java的可配置性. 1.1 通过反射构建对象(无参数): 例如我们使用 ReflectS ...
- Java反射获取对象VO的属性值(通过Getter方法)
有时候,需要动态获取对象的属性值. 比如,给你一个List,要你遍历这个List的对象的属性,而这个List里的对象并不固定.比如,这次User,下次可能是Company. e.g. 这次我需要做一个 ...
- 第五课 JAVA反射获取对象属性和方法(通过配置文件)
Service1.java package reflection; public class Service1 { public void doService1(){ System.out.print ...
- 用Java反射输出对象的所有属性的值
获取对象的类类型 Class cls = obj.getClass(); 用类类型获取属性数组 getFields()获取的是共有属性 getDeclaredFields()可以获取所有属性 Fiel ...
- 第五课 JAVA反射获取对象属性和方法
package com.hero; import java.lang.reflect.Field; public class TestReflction5 { public static void m ...
随机推荐
- MySQL笔记--查询语句实践
有一个用户表,属性为 id,age,buytime 创建表以及插入数据的语句 CREATE TABLE USER( id INT, age INT, buytime INT ) ,,); ,,); , ...
- Oracle除替换去掉换行符的方法
特殊符号ascii定义 : 换行符和回车符都要干掉. 制表符 chr(9) 换行符 chr(10) 回车符 chr(13) select replace(replace(列名,CHR(10),''), ...
- FLASK安装--兼收EZ_INSTALL及PIP
参考URL: http://www.cnblogs.com/haython/p/3970426.html http://www.pythondoc.com/flask/installation.htm ...
- PS/2接口
ps/2接口标准的发展过程 随着计算机工业的发展,作为计算机最常用输入设备的键盘也日新月异.1981年IBM推出了IBM pc/XT键盘及其接口标准.该标准定义了83键,采用5脚DIN连接器和简单的串 ...
- 7.5 Point-in-Time (Incremental) Recovery Using the Binary Log 使用binay log 基于时间点恢复
7.5 Point-in-Time (Incremental) Recovery Using the Binary Log 使用binay log 基于时间点恢复 7.5.1 Point-in-Tim ...
- R语言笔记
R语言笔记 学习R语言对我来说有好几个地方需要注意的,我觉得这样的经验也适用于学习其他的新的语言. 语言的目标 我理解语言的目标就是这个语言是用来做什么的,为什么样的任务服务的,也就是设计这个语言的动 ...
- List的数据结构
从这张图片说起:TreeList的实现结构: 首先是构建函数 TreeList(Collection coll),调用增加函数: public void add(int index, Object o ...
- Hadoop的基本命令【转载】
在这篇文章中,我们默认认为Hadoop环境已经由运维人员配置好直接可以使用. 假设Hadoop的安装目录HADOOP_HOME为/home/admin/hadoop. 启动与关闭 启动HADOOP 进 ...
- [LeetCode] 204. Count Primes 解题思路
Count the number of prime numbers less than a non-negative number, n. 问题:找出所有小于 n 的素数. 题目很简洁,但是算法实现的 ...
- ORACLE 索引概述
索引是数据库中一种可选的数据结构,她通常与表或簇相关.用户可以在表的一列或数列上建立索引,以提高在此表上执行 SQL 语句的性能.就像本文档的索引可以帮助读者快速定位所需信息一样,Oracle 的索引 ...