java反射调用set方法时如果让参数做自动类型转换

这段时间学习java的反射机制想实现一个功能:遍历一个Map,然后利用反射机制调用BO的set方法,完成BO属性的自动注入。这样设计的初衷是解决Excel数据导入问题中的Map数据填充BO这一过程。

 

下面是一个BO:

 

package com.handlewell.testOnly.persistence;



import java.io.Serializable;
import java.util.Date;

public class StudentBO implements Serializable{

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private Long id;
    
    private String sname;
    
    private Integer age;
    
    private Date birthDate;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    .
    .
                .
    
}

 

为了代码的复用性和做Excel文件处理时的灵活性决定使用Enum来指定文件中表头和BO中属性方法的对应关系,下面是使用的Enum类:

 

public enum ExclTableField {
    
    Sname("姓名"),
    Age("年龄"),
    BirthDate("生日");
    
    private String description;
    
    private ExclTableField(String description){
        this.description = description;
    }
    
    public String getDescription() {
        return description;
    }

}

 

有了BO和Enum我们需要一个工具类来完成数据的填充,这个工具类必须能完成各种BO的填充,所以必须使用泛型和反射。

下面是工具类的代码:

 

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Excle2EntityUtil<T> {
    
    private T entity;
    
    public Excle2EntityUtil(T entity){
        this.entity = entity;
    }

    public void doInitEntity(String methodName , Object obj) 
        throws SecurityException, NoSuchMethodException, IllegalArgumentException, 
        IllegalAccessException, InvocationTargetException{
        
        //根据传入的属性名称构造属性的set方法名
        methodName = "set"+methodName;
        System.out.println("Method Name --"+methodName);
        Method[] methods = entity.getClass().getMethods();
        for(Method method:methods){
            //如果方法同名则执行该方法(不能用于BO中有重载方法的情况)
            if(methodName.equals(method.getName())){
                
                //这里如何做类型转换???????????*
                method.invoke(entity, obj);
            }
        }
    }
}

 在做测试的时候因从模拟的数据Map中得到的Age是一个String类型的,在反射的方法调用时这个set方法应该传入的是int类型的数据。所以会抛出java.lang.IllegalArgumentException: argument type mismatch这样的异常。

 

package com.handlewell.testOnly.services.impl;

import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

import com.handlewell.testOnly.persistence.StudentBO;
import com.handlewell.testOnly.support.ExclTableField;
import com.handlewell.testOnly.support.Excle2EntityUtil;

public class InvokeMethodTest {
    public static void main(String[] args) {
        
        /**测试,手动构造一个Map,模拟从Excel中读出的数据Map----begin*/
        Map<String, Object> studentMap = new LinkedHashMap<String, Object>();
        studentMap.put("姓名", "gaojun");
        String age = "24";
        studentMap.put("年龄", age);
        Date date = new Date();
        studentMap.put("生日", date);
        /**测试,手动构造一个Map,模拟从Excel中读出的数据Map----end*/
        
        StudentBO student = new StudentBO();
        
        //使用StudentBO构造一个数据填充工具实例
        Excle2EntityUtil<StudentBO> studentEntityUtil = new Excle2EntityUtil<StudentBO>(student);
        for (ExclTableField tableField : ExclTableField.values()) {
            //根据Enum上属性名称拿到属性的值,这里所有的属性值都是一个Object类型。
            Object obj = studentMap.get(tableField.getDescription());
            try {
                //传入属性名和值,完成自动填充BO属性。
                studentEntityUtil.doInitEntity(tableField.toString(), obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        System.out.println(student.getSname());
        System.out.println(student.getAge());
        System.out.println(student.getBirthDate());
    }
}

 

 

请问:这里要如何解决这个类型转换的问题呢?有没有什么方法可以让方法在执行时自动将Object类型转换为所需要的类型呢?

6个回答

Excle2EntityUtil类的中方法改成这样试试,现在能想到的就是这样if..else if 一个一个遍历,这些对类的反射操作以及类型转换在BeanUtils都有,你可以用下,可以省很多时间,它里面都有一些常用的类型转换器,如果你的需求中用到自定义转换还可以继续它的接口实现

[code="java"]public void doInitEntity(String methodName, Object obj) throws Exception {
//
methodName = "set" + methodName;
Method[] methods = entity.getClass().getMethods();
for (Method method : methods) {
if (methodName.equals(method.getName())) {
Class<?>[] clazz = method.getParameterTypes();
String type = clazz[0].getName();
if(type.equals("java.lang.String")){
method.invoke(entity,(String)obj);
}
else if(type.equals("java.util.Date")){
method.invoke(entity, (Date)obj);
}
else if(type.equals("java.lang.Integer")){
method.invoke(entity, new Integer((String)obj));
}else{
//........
}
}
}
}[/code]

bendan123812
bendan123812 恩,看来只有自己去转换了。回去学习下BeanUtils的源码。
大约 7 年之前 回复

都是判断去比的.

就算是框架也一样.

只能是判断当前的obj 的class 是不是 你期望的类的class 如果一样就行.

如果你都是引用类型 用instanceof就可以了.

如果你希望支持 int 这种普通类型. 那你就要用class 比较.

如果你期望动态 那么你就把比较的信息通过配置文件配置. 来支持你的类型扩展.

bendan123812
bendan123812 恩,看来还是要一个一个比对的,准备自己写个转换工具
大约 7 年之前 回复

从Excel中读出的数据Map,请问一下,这个是如何实现的呢?谢谢!

bendan123812
bendan123812 这个有很多种方法了,看你的设计,但是必须有一个标准,用户上传的文件必须是符合你的标准的。比如数据的列的顺序不能变,或者是列的名称不能变,这些标准都是为了你把Map的数据填充到BO中。如何把Excel中的数据读出一个Map,这个java提供了API JXL,不过这个api对excel2007及以上的版本可像不支持。如果要读2007以上的版本文件请用apache的poi。具体的操作也就是遍历文件的行啊,列啊什么的,可以看下例子学习一下。
大约 7 年之前 回复

自动是不可能的,你可以看下Method有没有获得传入参数类型的方法,如果有的话,再把object转换成这个类型。反正就是这个思路

可以参考spring的converter

请使用Field来进行设置值.

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!