bendan123812
2012-08-06 14:14
浏览 1.1k
已采纳

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条回答 默认 最新

  • iteye_7115 2012-08-06 16:12
    已采纳

    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]

    点赞 打赏 评论
  • gongxuxuxuxux 2012-08-06 15:53

    都是判断去比的.

    就算是框架也一样.

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

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

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

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

    点赞 打赏 评论
  • 蚂蚁与咖啡的故事 2012-08-06 21:59

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

    点赞 打赏 评论
  • do81788009 2012-08-07 01:24

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

    点赞 打赏 评论
  • jinnianshilongnian 2012-08-07 08:28

    可以参考spring的converter

    点赞 打赏 评论
  • iteye_20658 2012-08-07 10:17

    请使用Field来进行设置值.

    点赞 打赏 评论

相关推荐 更多相似问题