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

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]

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

悬赏问题

  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置