- 大家是不是经常遇到一种情况,比如两个对象,Member和MemberView,很多时候我们都有可能进行相互转换,那么我们常用的方法就是,把其中一个中的值挨个get出来,然后再挨个set到另一个中去,接下来我介绍的这种方法就可以解决这种问题造成的困扰,多的不说,看下面代码:
package copyPojoDemo;
public class Member{
private String username;
private String password;
private String truename;
private String nickname;
private String gender;
private int age;
@Override
public String toString(){
return (username==null?"":"username:" + username) +
(password==null?"":" password:" + password) +
(truename==null?"":" truename:" + truename) +
(nickname==null?"":" nickname:" + nickname) +
(gender==null?"":" gender:" + gender) +
" age:" + age;
}
}
package copyPojoDemo;
public class MemberView{
private String username;
private String password;
private String truename;
private String nickname;
private String gender;
private int age;
}
package copyPojoDemo;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class ReflectionDemo{
public static void main(String args[]){
MemberView fromObject = new MemberView();
fromObject.setUsername("sunchenbin");
fromObject.setPassword("111111");
fromObject.setAge(21);
fromObject.setGender("男");
fromObject.setNickname("墨白");
String[] fields = new String[]{}; // 没有设置属性,默认去对比两个对象
//String[] fields = new String[]{"username","password","gender"};
try{
// 将一个对象转换成另一个对象,并把指定的属性值传递给这个对象,如果不指定默认去匹配两个对象的属性,存在则赋值
Member member = (Member) constructObject(fromObject,new Member(),fields);
System.out.println(member.toString());
}catch (Exception e){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static Object constructObject(Object fromObject,Object toObject,String[] fields) throws Exception{
// 数据源的class
Class fromClass = fromObject.getClass();
// 目标的class
Class toClass = toObject.getClass();
for (String field : fields){
try{
// 获取fromClass的Field
Field fromDeclaredField = fromClass.getDeclaredField(field);
fromDeclaredField.setAccessible(true);
// 从fromClass中获取属性的值
Object value = fromDeclaredField.get(fromObject);
// 获取toClass的Field
Field toDeclaredField = toClass.getDeclaredField(field);
toDeclaredField.setAccessible(true);
// 将fromClass中该属性的值设置给toClass中的该属性
toDeclaredField.set(toObject, value);
}catch (NoSuchFieldException e){
System.out.println(field+"属性不存在");
e.printStackTrace();
}
}
// 如果没有传递属性过来,那么默认对比from和to中的属性,存在的进行赋值操作
if(fields.length == 0){
Field[] fromDeclaredFields = fromClass.getDeclaredFields();
Field[] toDeclaredFields = toClass.getDeclaredFields();
List<String> fromList = new ArrayList<String>();
List<String> toList = new ArrayList<String>();
// 取出from中所有field
for (Field field : fromDeclaredFields){
field.setAccessible(true);
fromList.add(field.getName());
}
// 取出to中所有field
for (Field field : toDeclaredFields){
field.setAccessible(true);
toList.add(field.getName());
}
// 循环from属性list
for (String name : fromList){
// to中是否包含该属性
if(toList.contains(name)){
// 包含先进行取值
Field fromDeclaredField = fromClass.getDeclaredField(name);
fromDeclaredField.setAccessible(true);
Object value = fromDeclaredField.get(fromObject);
// 进行赋值操作
Field toDeclaredField = toClass.getDeclaredField(name);
toDeclaredField.setAccessible(true);
toDeclaredField.set(toObject, value);
}
}
}
return toObject;
}
}
以上基本就可以实现我们想要达到的效果了。
- 还有一种场合,程序执行时,要动态加载某个类并执行方法,那么看下面代码:
package initLoadDemo;
public class TestClass{
public double eachOrtherToAdd(Integer one,Double two,Integer three){
return one+two+three;
}
}
package initLoadDemo;
import java.lang.reflect.Method;
public class ReflectionDemo{
public static void main(String args[]){
String className = "initLoadDemo.TestClass";
String methodName = "eachOrtherToAdd";
String[] paramTypes = new String[]{"Integer","Double","int"};
String[] paramValues = new String[]{"1","4.3321","5"};
// 动态加载对象并执行方法
initLoadClass(className, methodName, paramTypes, paramValues);
}
@SuppressWarnings("rawtypes")
private static void initLoadClass(String className,String methodName,String[] paramTypes,String[] paramValues){
try{
// 根据calssName得到class对象
Class cls = Class.forName(className);
// 实例化对象
Object obj = cls.newInstance();
// 根据参数类型数组得到参数类型的Class数组
Class[] parameterTypes = constructTypes(paramTypes);
// 得到方法
Method method = cls.getMethod(methodName, parameterTypes);
// 根据参数类型数组和参数值数组得到参数值的obj数组
Object[] parameterValues = constructValues(paramTypes,paramValues);
// 执行这个方法并返回obj值
Object returnValue = method.invoke(obj, parameterValues);
System.out.println("结果:"+returnValue);
}catch (Exception e){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static Object[] constructValues(String[] paramTypes,String[] paramValues){
Object[] obj = new Object[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++){
if(paramTypes[i] != null && !paramTypes[i].trim().equals("")){
if ("Integer".equals(paramTypes[i]) || "int".equals(paramTypes[i])){
obj[i] = Integer.parseInt(paramValues[i]);
}else if ("Double".equals(paramTypes[i]) || "double".equals(paramTypes[i])){
obj[i] = Double.parseDouble(paramValues[i]);
}else if ("Float".equals(paramTypes[i]) || "float".equals(paramTypes[i])){
obj[i] = Float.parseFloat(paramValues[i]);
}else{
obj[i] = paramTypes[i];
}
}
}
return obj;
}
@SuppressWarnings("rawtypes")
private static Class[] constructTypes(String[] paramTypes){
Class[] cls = new Class[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++){
if(paramTypes[i] != null && !paramTypes[i].trim().equals("")){
if ("Integer".equals(paramTypes[i]) || "int".equals(paramTypes[i])){
cls[i] = Integer.class;
}else if ("Double".equals(paramTypes[i]) || "double".equals(paramTypes[i])){
cls[i] = Double.class;
}else if ("Float".equals(paramTypes[i]) || "float".equals(paramTypes[i])){
cls[i] = Float.class;
}else{
cls[i] = String.class;
}
}
}
return cls;
}
}
详解就不说了,说起java的反射机制,基本就会想到4个类,Field、Constractor、Method、Class,依次是分别封装了反射的属性、构造函数、方法,剩下的Class就不多说了,基本掌握这的应用就OK了,至于业务场景还有很多。