-
Java反射机制调用对象的方法 —— 将一个对象的属性值赋值给另一个对象的属性
2019-06-05 14:01:06通过反射机制调用对象的某个方法 -- 将一个对象的属性值赋值给另一个对象的属性开发环境创建对象UserOne、UserTwo编写基于反射的工具类测试结果预留占位 模拟一个场景: 众所周知,EasyExcel导出Excel文档是依赖于...通过反射机制调用对象的某个方法 -- 将一个对象的属性值赋值给另一个对象的属性
模拟一个场景:
众所周知,EasyExcel导出Excel文档是依赖于注解完成的,在实体类需要导出的属性上面加上注解,导出的时候会自动识别该属性。
假如我们现在需要导出用户的信息,又不想污染原本的实体类,又要过滤掉password这个属性。那么我们可以另外创建一个实体类,不包含password属性。然后我们将查到的用户信息,赋值给新创建的对象即可。
赋值这一步是比较繁琐的,我们需要写循环,然后判断,然后赋值。等将来需要导出管理员信息的时候我们又要写循环,然后判断,然后赋值、、、
怎么能写一个共用的方法去帮我们做循环、判断、赋值这些事呢?源对象类型不确定,目标对象类型不确定。
于是,反射机制来了。它来了,它来了,它哼着小曲走来了、、、
通过 Java 的反射机制,程序员可以更深入地控制程序的运行过程。例如,在程序运行时由用户输入一个类名,然后动态获取该类拥有的构造、属性和方法,甚至调用任意类的任意方法。
Java 反射机制主要提供了以下功能,这些功能都位于 java.lang.reflect包下。
- 在运行时判断任意一个对象所属的类。
- 在运行时构造任意一个类的对象。
- 在运行时判断任意一个类所具有的成员变量和方法。
- 在运行时调用任意一个对象的方法。
- 生成动态代理。
开发环境
请参照: 基于SpringBoot构建分模块项目
创建对象UserOne、UserTwo
UserOne为与数据库表对应的实体类,UserTwo为即将要通过EasyExcel导出的对象
package com.wayne.common.entity; /** * @author Wayne * @date 2019/6/5 */ public class UserOne { private Integer id; private String username; private String password; // Getter and Setter 、、、 }
package com.wayne.common.dto; /** * @author Wayne * @date 2019/6/5 */ public class UserTwo { private Integer id; private String username; // Getter and Setter 、、、 }
编写基于反射的工具类
通过反射创建对象、调用方法
package com.wayne.common.utils; import com.google.common.collect.Lists; import com.wayne.common.exception.CopyPropertyException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.List; /** * @author Wayne * @date 2019/6/5 */ public class BaseUtil { /** * 将一个集合中对象的值拷贝到另一个对象,属性相同即赋值 * @param source 源数据,将此对象数据取出 * @param tClass 目标对象,将取出的数据赋值到该对象中 * @param <T> 源数据类型 * @param <E> 目标数据类型 * @return 被赋值后的目标对象集合 * @throws CopyPropertyException 自定义异常,通过反射创建对象或调用方法时抛出的异常 */ public static <T, E> List<E> copyProperties(List<T> source, Class<E> tClass) throws CopyPropertyException { // 判断传入源数据是否为空,如果空,则抛自定义异常 if(null == source) { throw new CopyPropertyException("数据源为空"); } // 创建一个集合,用于存储目标对象,全部数据抓换完成后,将该集合返回 List<E> targetList = Lists.newArrayList(); // 循环取到单个源对象 for(T t : source) { // 获取源对象的类的详情信息 Class<?> sClass = t.getClass(); // 获取源对象的所有属性 Field[] sFields = sClass.getDeclaredFields(); // 获取目标对象的所有属性 Field[] tFields = tClass.getDeclaredFields(); E target; try { // 通过类的详情信息,创建目标对象 这一步等同于UserTwo target = new UserTwo(); target = tClass.newInstance(); } catch (Exception e) { e.printStackTrace(); throw new CopyPropertyException("目标对象创建失败"); } // 循环取到源对象的单个属性 for(Field sField : sFields) { // 循环取到目标对象的单个属性 for(Field tField : tFields) { // 判断源对象的属性名、属性类型是否和目标对象的属性名、属性类型一致 if(sField.getName().equals(tField.getName()) && sField.getGenericType().equals(tField.getGenericType())) { try { // 获取源对象的属性名,将属性名首字母大写,拼接如:getUsername、getId的字符串 String sName = sField.getName(); char[] sChars = sName.toCharArray(); sChars[0] -= 32; String sMethodName = "get" + String.valueOf(sChars); // 获得属性的get方法 Method sMethod = sClass.getMethod(sMethodName); // 调用get方法 Object sFieldValue = sMethod.invoke(t); // 获取目标对象的属性名,将属性名首字母大写,拼接如:setUsername、setId的字符串 String tName = tField.getName(); char[] tChars = tName.toCharArray(); tChars[0] -= 32; String tMethodName = "set" + String.valueOf(tChars); // 获得属性的set方法 Method tMethod = tClass.getMethod(tMethodName, tField.getType()); // 调用方法,并将源对象get方法返回值作为参数传入 tMethod.invoke(target, sFieldValue); break; } catch (Exception e) { e.printStackTrace(); throw new CopyPropertyException("转换失败,请检查属性类型是否匹配"); } } } } // 将通过反射创建的目标对象放入集合中 targetList.add(target); } // 返回集合 return targetList; } }
测试结果
预留占位
开发怎能不留扩展字段 (¬_¬)…
-
java中如何用反射创建一个对象
2015-12-14 18:21:22java中如何用反射创建一个对象 如何理解java的反射,反射是一种怎么样的机制呢 -
java用反射将一个对象复制给另一个对象
2018-04-29 13:28:02@SneakyThrows public static Object objectClone(Object newObject,Object oldObject){ Field[] oldFields = oldObject.getClass().getDeclaredFields(); Field newField; for (Field ...@SneakyThrows public static Object objectClone(Object newObject,Object oldObject){ Field[] oldFields = oldObject.getClass().getDeclaredFields(); Field newField; for (Field oldField : oldFields){ oldField.setAccessible(true); newField = newObject.getClass().getDeclaredField(oldField.getName()); newField.setAccessible(true); newField.set(newObject,oldField.get(oldObject)); } return newObject; }
-
利用反射,将一个java bean对象转换为另一个对象
2019-06-28 15:09:52* 将一个对象转换为另一个对象需要两个bean对象的变量相同 * * @param <T1> 要转换的对象 * @param <T2> 转换后的类 * @param orimodel 要转换的对象 * @param castClass 转换后的类 * @return .../** * 将一个对象转换为另一个对象需要两个bean对象的变量相同 * * @param <T1> 要转换的对象 * @param <T2> 转换后的类 * @param orimodel 要转换的对象 * @param castClass 转换后的类 * @return 转换后的对象 */ public static <T1, T2> T2 convertBean(T1 orimodel, Class<T2> castClass) { T2 returnModel; try { returnModel = castClass.newInstance(); } catch (Exception e) { throw new RuntimeException("创建" + castClass.getName() + "对象失败"); } //要转换的字段集合 List<Field> fieldlist = new ArrayList<Field>(); final String objClass = "java.lang.object"; //循环获取要转换的字段,包括父类的字段 while (castClass != null && !objClass.equals(castClass.getName().toLowerCase())) { fieldlist.addAll(Arrays.asList(castClass.getDeclaredFields())); //得到父类,然后赋给自己 castClass = (Class<T2>) castClass.getSuperclass(); } for (Field field : fieldlist) { PropertyDescriptor getpd; PropertyDescriptor setpd; try { getpd = new PropertyDescriptor(field.getName(), orimodel.getClass()); setpd = new PropertyDescriptor(field.getName(), returnModel.getClass()); } catch (Exception e) { continue; } try { Method getMethod = getpd.getReadMethod(); Object transValue = getMethod.invoke(orimodel); Method setMethod = setpd.getWriteMethod(); setMethod.invoke(returnModel, transValue); } catch (Exception e) { throw new RuntimeException("cast " + orimodel.getClass().getName() + "to " + castClass.getName() + " failed"); } } return returnModel; }
-
使用反射将一个对象的值复制给另一个对象(同一个对象或者基于同一个基类)
2018-06-25 14:21:54第一个方法是一个类的不同实例化对象,比如类A,实例化对象a1,a2,:(使用的方法是得到类的属性名)/** * *<p> *@description 转换javabean ,将class2中的属性值赋值给class1,如果class...第一个方法是一个类的不同实例化对象,比如类A,实例化对象a1,a2,:(使用的方法是得到类的属性名)
/** * *<p> *@description 转换javabean ,将class2中的属性值赋值给class1,如果class1属性有值,则不覆盖 *</p> *@param class1 基准类,被赋值对象 *@param class2 提供数据的对象 *@throws Exception * @see */ private void converJavaBean(Object class1, Object class2) { Class<?> clazz1 = class1.getClass(); Class<?> clazz2 = class2.getClass(); Field[] fields1 = clazz1.getDeclaredFields(); Field[] fields2 = clazz2.getDeclaredFields(); for (int i = 0; i < fields1.length; i++) { try { fields1[i].setAccessible(true); fields2[i].setAccessible(true); Object obg1 = fields1[i].get(class1); Object obg2 = fields2[i].get(class2); if (null == fields1[i].get(class1) && null != fields2[i].get(class2)) { fields1[i].set(class1, fields2[i].get(class2)); } } catch (Exception e) { e.printStackTrace(); } } }
第二个方法得到get和set方法进行赋值,比第一个功能强大,只要有相同的属性名都可以
import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; /** * * <p> * * @description 转换javabean ,将class2中的属性值赋值给class1,如果class1属性有值,则不覆盖 * ,前提条件是有相同的属性名 * </p> * @param class1 * 基准类,被赋值对象 * @param class2 * 提供数据的对象 * @throws Exception * @author ex_dingyongbiao * @see */ public class CopyBeans { /** * @param src 获取属性值 * @param dest 给属性赋值 */ public static void copy(Object class1, Object class2) { try { Class<?> clazz1 = class1.getClass(); Class<?> clazz2 = class2.getClass(); // 得到method方法 Method[] method1 = clazz1.getMethods(); Method[] method2 = clazz2.getMethods(); int length1 = method1.length; int length2 = method2.length; if (length1 != 0 && length2 != 0) { // 创建一个get方法数组,专门存放class2的get方法。 Method[] get = new Method[length2]; for (int i = 0, j = 0; i < length2; i++) { if (method2[i].getName().indexOf("get") == 0) { get[j] = method2[i]; ++j; } } for (int i = 0; i < get.length; i++) { if (get[i] == null)// 数组初始化的长度多于get方法,所以数组后面的部分是null continue; // 得到get方法的值,判断时候为null,如果为null则进行下一个循环 Object value = get[i].invoke(class2, new Object[] {}); if (null == value) continue; // 得到get方法的名称 例如:getXxxx String getName = get[i].getName(); // 得到set方法的时候传入的参数类型,就是get方法的返回类型 Class<?> paramType = get[i].getReturnType(); Method getMethod = null; try { // 判断在class1中时候有class2中的get方法,如果没有则抛异常继续循环 getMethod = clazz1.getMethod(getName, new Class[] {}); } catch (NoSuchMethodException e) { continue; } // class1的get方法不为空并且class1中get方法得到的值为空,进行赋值,如果class1属性原来有值,则跳过 if (null == getMethod || null != getMethod.invoke(class1, new Object[] {})) continue; // 通过getName 例如getXxxx 截取后得到Xxxx,然后在前面加上set,就组装成set的方法名 String setName = "set" + getName.substring(3); // 得到class1的set方法,并调用 Method setMethod = clazz1.getMethod(setName, paramType); setMethod.invoke(class1, value); } } } catch(Exception e) { System.out.println(e); } } }
推荐使用第二种方法。
-
【反射】案例讲解:通过反射机制来复制一个对象
2016-12-08 20:54:28Student类,有属性id, name, age, 还有对应的get,set方法和构造方法。 现产生一个Student对象。通过反射复制此Student对象。复制时,并不知道源对象具体的属性名称。 -
Java反射应用-遍历一个对象的属性和值
2019-01-17 16:30:28本文是Java反射的一个常见的案例,常见的情况是,给到一个对象,需要把对象的每个属性和值重新生成一个Map或者Array,这个时候就是要要到反射啦,不多说,上干货: public static ArrayList<NameValuePair&... -
Java反射之通过反射获取一个对象的方法信息
2015-04-24 20:54:04以下代码为一个工具类 package com.imooc.reflect; import java.lang.reflect.Method; public class ClassUtil { public static void printClassMessage(Object obj){ //要获取类的信息,首先要获取类的类... -
JAVA反射初探之获取一个实例对象
2018-02-21 20:41:49先来说一下,由于本人最近开始学习Spring,水平有限,希望各位大佬多多发表自己的意见,指出我的纰漏,甚是感谢!下面进入正题: 反射,相信各位对这个名词...在运行的时候才决定要一个什么样的对象,这种情况下我... -
通过反射将一个对象的值赋给另一个对象中对应的属性 不需要用set、get
2017-11-05 02:41:15/** * @method test * @author BinCain * @return void * @date 2017/11/5 0005 2:19 * @Description: 将srcObj对象字段的值拷贝到destObj字段(前提:两个对象中的字段名相同时) ... -
【反射机制】两个类名不同但其属性相同的对象,如何将一个对象的值赋给另外一个对象
2017-12-14 09:14:34最近公司需要用线程迁移一张表(业务表)的数据至另外一张表(备份表)中,两张表的字段一样,如何...后来想到可以用反射的机制去进行赋值,下面是我的测试代码:(我们公司对象属性都是String类型) public class Re -
java反射——获取一个Object对象内的一切!
2017-12-18 01:11:06有些时候你明明知道这个object里面是什么,但是因为种种原因,你不能将它转化成一个对象,只是想单纯地提取出这个object里的一些东西,这个时候就需要用反射了。 假如你这个类是这样的: private class User... -
如何根据类的名称来实例出一个对象——JAVA的反射机制
2019-10-14 19:47:30如何根据类的名称来实例出一个对象——JAVA的反射机制什么是反射机制?反射机制的使用类的结构主函数最终输出: 原文链接:http://www.starchou.cn/detail/5 什么是反射机制? 要想搞清楚什么叫反射机制,我们首先要... -
反射第三步 : 通过反射获取某一个类的 构造器Constructor 并通过反射创建对象
2017-08-21 11:42:42* 反射第三步 : 通过反射获取某一个类的 构造器Constructor 并通过反射创建对象 * * 带有 “Declared”的方法 无论什么访问权限的构造器都可访问 * 不带有 “Declared”的方法 只可访问p -
Java 通过反射获取一个Field对象的泛型类型
2016-12-10 11:57:02参考之后就要自己封装一个,所以这里小金子封装了对一个字段获取这个...* 获取某一个字段上面的泛型参数数组,典型的就是获取List对象里面是啥参数 * * @param f * @return */ public static Class[] getParame -
反射、类加载和new一个对象的过程的底层
2019-09-27 21:58:02这段时间比较好奇类加载的一个过程,正好在知乎上看到了其中一个比较有意思的地方,就是创建一个对象的过程,描述的更加底层,这里做一个分享。 创建对象的过程,或者说new一个对象的过程如下: ... -
一个反射将对象转化为sql语句的实例
2014-02-20 15:22:56//一个反射将对象转化为sql语句的实例。转自weiluo12 public class Student { private int studid; private String major; private double age; public Student() { super(); } public Stude -
利用反射拷贝对应的属性值到另一个对象中
2016-08-05 23:47:10开发代码中遇到两个对象具有很多相同的属性名称并且类型一致,为了减少编码和提高开发效率,利用反射原理来解析某个对象中的属性值拷贝到另一个对象与之对应的属性中。 -
Java的反射机制1——实例化一个对象
2016-05-17 10:48:37看了一下Java OOP的项目,在创建门禁卡...其实理解Java的反射和理解JavaScript的eval函数一样,都是将一个字符型数据转换为相应的类、属性和方法;通过下面的例子来熟悉一下Java的反射; 首先定义一个教员类,如下: -
Java中利用反射去判断一个对象所有属性是否都为空
2020-08-12 16:38:06被判断的类对象,随便写的一个 针对第一种情况,直接使用null进行比较即可 但是,只要学过java的人都知道,这个判断永远都是true,因为上面对象中定义了相应的属性,尽管对象的属性是空的,但是对象不为空,... -
反射机制 创建对象
2018-01-12 17:44:36与传统的通过new 来获取对象的方式不同 反射机制,会先拿到Hero的“类对象”,然后...通过反射机制创建一个对象 package reflection; import java.lang.reflect.Constructor; import charactor.Hero; public class -
反射:动态执行一个对象的方法
2014-09-21 01:39:04public Object invoke(Object obj, String methodName, Object... args) throws Exception { Class cls = obj.getClass(); Class[] paramTypes = new Class[args.length]; for (int i = 0;...paramTypes[i] = a -
Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值
2018-05-14 13:11:07Java循环一个对象的所有属性,并通过反射给这些属性赋值/取值 说到循环遍历,最常见的遍历数组/列表、Map等。但是,在开发过程中,有时需要循环遍历一个对象的所有属性。遍历对象的属性该如何遍历呢?查了一下资料... -
使用反射复制一个JavaBean的对象
2012-05-12 10:58:15代码中有一个Customer1的JavaBean,通过反射复制了一个Customer1类的对象,为customerCopy,程序中的new Class[] { }是一种快捷方式,获得方法的引用。[]中用来放参数,{}里面可以放置方法的返回类型。new Class[] ...
收藏数
28,399
精华内容
11,359