Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/357.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中,如何根据输入数据的顺序/名称动态调用不同的setter方法?_Java_Web Services_Apache Poi - Fatal编程技术网

在java中,如何根据输入数据的顺序/名称动态调用不同的setter方法?

在java中,如何根据输入数据的顺序/名称动态调用不同的setter方法?,java,web-services,apache-poi,Java,Web Services,Apache Poi,我班上大约有20个变量。我需要阅读excel工作表,然后根据变量的名称相应地获取数据并将其设置在DTO类中。 除2外,所有变量都是字符串。这两个是数字。 现在我将从excel中获取单行,接下来我必须获取每个单元格的内容,并根据单元格的数据/索引顺序显式调用setter方法。有没有办法让这一切自动化? 我的意思是,有没有办法为特定的索引调用特定的方法?我们可以在数组中的某个位置定义它的关系并将它们关联起来吗 请帮助。 假设3个,而不是20个变量 假设excel工作表包含以下列: 第1列=名称 第

我班上大约有20个变量。我需要阅读excel工作表,然后根据变量的名称相应地获取数据并将其设置在DTO类中。 除2外,所有变量都是字符串。这两个是数字。 现在我将从excel中获取单行,接下来我必须获取每个单元格的内容,并根据单元格的数据/索引顺序显式调用setter方法。有没有办法让这一切自动化? 我的意思是,有没有办法为特定的索引调用特定的方法?我们可以在数组中的某个位置定义它的关系并将它们关联起来吗

请帮助。

  • 假设3个,而不是20个变量

  • 假设excel工作表包含以下列:

    • 第1列=名称
    • 第2列=街道
    • 第3列=数字
  • 假设以下是您的班级:

    包com.johanw.stackoverflow.dynamicinit

    公共类MyObjectImpl{ 私有字符串名称; 私家弦街;; 私有整数

    public MyObjectImpl() {
    }
    
    public MyObjectImpl(String name, String street, int number) {
        this.name = name;
        this.street = street;
        this.number = number;
    }
    
    public String getName() {
        return name;
    }
    
    public void setName(String name) {
        this.name = name;
    }
    
    public String getStreet() {
        return street;
    }
    
    public void setStreet(String street) {
        this.street = street;
    }
    
    public int getNumber() {
        return number;
    }
    
    public void setNumber(int number) {
        this.number = number;
    }
    
    public void setNumberAsString(String number) {
        this.number = Integer.valueOf(number);
    }
    
    }


  • 我想到了两种不同的解决方案

    解决方案1
  • 第一种解决方案是使用反射和方法名列表,这些方法名按照您想要初始化对象的顺序排列,如下面的代码所示

    包com.johanw.stackoverflow.dynamicinit

    导入java.lang.reflect.InvocationTargetException; 导入java.lang.reflect.Method

    公共类PopulateObjects2{ 接口初始化字段操作{ void初始化(MyObjectImpl对象,字符串值); }


    重新组合 我建议使用第二种方法,即不使用反射。但是,如果列不固定,您可能有理由希望能够使用反射,并且您可以从某些配置或电子表格标题中检索这些值


    代码 以下代码/项目可在



    我希望这能有所帮助。

    有关
    MyObjectImpl
    ,请参阅s

    解决方案1:构造函数接受数组 只需创建一个接受带值数组的构造函数。您必须列出字段号和设置之间的所有映射,但您必须在所有解决方案中执行类似的操作

    public MyObjectImpl(String[] values) {
        this.name = values[0];
        this.street = values[1];
        this.number = Integer.valueOf(values[0]);
        // ...
    }
    
    解决方案2:使用mapper函数定义地图 有点类似于@johanwitters的解决方案2,但只使用了标准的Java函数接口和方法引用,这使它更加紧凑

    public static void main(String[] args) {
    
        String[] values = { /* data from file */};
    
        Map<Integer, BiConsumer<MyObjectImpl, String>> mappers = new HashMap<>();
        mappers.put(0, MyObjectImpl::setName);
        mappers.put(1, MyObjectImpl::setStreet);
        mappers.put(2, asInt(MyObjectImpl::setNumber));
        // ...
    
        MyObjectImpl obj = retrieveWithValues(values, mappers);
    
    }
    
    private static BiConsumer<MyObjectImpl, String> asInt(BiConsumer<MyObjectImpl, Integer> intConsumer) {
        return (obj, i) ->  intConsumer.accept(obj, Integer.valueOf(i));
    }
    
    private static MyObjectImpl retrieveWithValues(String[] values, Map<Integer, BiConsumer<MyObjectImpl, String>> mappers) {
        if (values.length != mappers.size()) {
            return null;
        }
        MyObjectImpl obj = new MyObjectImpl();
        for (int i = 0; i < mappers.size(); i++) {
            mappers.get(i).accept(obj, values[i]);
        }
        return obj;
    }
    
    publicstaticvoidmain(字符串[]args){
    字符串[]值={/*文件中的数据*/};
    Map mappers=newhashmap();
    put(0,MyObjectImpl::setName);
    put(1,MyObjectImpl::setStreet);
    put(2,asInt(MyObjectImpl::setNumber));
    // ...
    MyObjectImpl obj=检索值(值、映射器);
    }
    专用静态双消费者asInt(双消费者intConsumer){
    return(obj,i)->intConsumer.accept(obj,Integer.valueOf(i));
    }
    私有静态MyObjectImpl retrieveWithValues(字符串[]值,映射器){
    if(values.length!=mappers.size()){
    返回null;
    }
    MyObjectImpl obj=新的MyObjectImpl();
    对于(int i=0;i
    package com.johanw.stackoverflow.dynamicinit.init;
    
    import org.junit.Assert;
    import org.junit.Test;
    
    import java.lang.reflect.InvocationTargetException;
    import java.time.LocalDate;
    import java.util.Arrays;
    import java.util.Optional;
    import org.junit.Assert;
    import org.junit.Test;
    
    public class PopulateObjects {
        private String[] exampleRow = { "name", "street", "10"};
    
        @Test
        public void method1() {
            MyObjectImpl o = PopulateObjects1.retrieveWithValues(exampleRow);
            Assert.assertTrue(o.getName().equals("name"));
            Assert.assertTrue(o.getStreet().equals("street"));
            Assert.assertTrue(o.getNumber() == 10);
            System.out.println(o);
        }
    
        @Test
        public void method2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
            MyObjectImpl o = PopulateObjects2.retrieveWithValues(exampleRow);
            Assert.assertTrue(o.getName().equals("name"));
            Assert.assertTrue(o.getStreet().equals("street"));
            Assert.assertTrue(o.getNumber() == 10);
            System.out.println(o);
        }
    }
    
    public MyObjectImpl(String[] values) {
        this.name = values[0];
        this.street = values[1];
        this.number = Integer.valueOf(values[0]);
        // ...
    }
    
    public static void main(String[] args) {
    
        String[] values = { /* data from file */};
    
        Map<Integer, BiConsumer<MyObjectImpl, String>> mappers = new HashMap<>();
        mappers.put(0, MyObjectImpl::setName);
        mappers.put(1, MyObjectImpl::setStreet);
        mappers.put(2, asInt(MyObjectImpl::setNumber));
        // ...
    
        MyObjectImpl obj = retrieveWithValues(values, mappers);
    
    }
    
    private static BiConsumer<MyObjectImpl, String> asInt(BiConsumer<MyObjectImpl, Integer> intConsumer) {
        return (obj, i) ->  intConsumer.accept(obj, Integer.valueOf(i));
    }
    
    private static MyObjectImpl retrieveWithValues(String[] values, Map<Integer, BiConsumer<MyObjectImpl, String>> mappers) {
        if (values.length != mappers.size()) {
            return null;
        }
        MyObjectImpl obj = new MyObjectImpl();
        for (int i = 0; i < mappers.size(); i++) {
            mappers.get(i).accept(obj, values[i]);
        }
        return obj;
    }