有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Groovy中带参数的java创建方法dynamicali

我有一个要求,例如,我使用SuperCSV读取csv文件并映射到对象

SuperCSV有一个要求,如果标头指定字段名“firstName”,则需要在类中包含setFirstName()方法,否则会引发异常

现在如果我使用groovybeans,那么我不需要声明所有这些方法,只要声明变量就可以了

但我在寻找一个更动态的解决方案,我们甚至不必声明这些变量

例如,只要动态创建一个对象,并且使用groovy的动态方法创建特性,SuperCSV就能够找到setter

我查看了各种选项,如Expando、ExpandoMetaClass,但这些都不符合我的目的

任何答复都将不胜感激

以下是对我有用的代码片段,它对减少大量代码和不必要的逻辑非常有帮助:

    static def testBeanReader()
{
    ICsvBeanReader beanReader = null;
    try 
    {
        beanReader = new CsvBeanReader(new FileReader("src/test.csv"),
                                 CsvPreference.STANDARD_PREFERENCE);                      
    }
    catch(Exception e)      
    {

    }

    final String[] header = VirtualObject.getHeaders();
    final CellProcessor[] processors = VirtualObject.getProcessors();

    //Class c1 = createNewClass()

    //String s = createClass()
    def list = ["name", "age"]
    def c = (new GroovyShell().evaluate(createClass(list)) as Class)
    //println(c.methods.grep {it.name.startsWith("get")})

    GroovyObject groovyObject = (GroovyObject)(beanReader.read(c, header, processors))
    Object[] args = {};
    println(groovyObject.getProperty("name"))

}

     static def createClass(def list)
{
    String classDeclaration = "\nclass Test {\n"
    list.each 
    {
        classDeclaration+="def $it\n"
    } 

    classDeclaration+= """
    }
            return Test.class
                              """
    return  classDeclaration
}

这适用于supercsv,但可以用于一般java对象,只需对语法进行少量更改


共 (1) 个答案

  1. # 1 楼答案

    您不能使用GroovyShell动态地构造这些类吗

    def c = (new GroovyShell().evaluate("""
    class Test {
        def fileName // list properties here
    }
    return Test.class
    """) as Class)
    
    println(c.methods.grep {it.name.startsWith("set")})
    
    def m = (c as Class).getMethod("setFileName", [Object] as Class[])
    // We, and I suppose SuperCSV, can access method via Reflexion API
    

    这是不安全的,但它会动态创建与Java兼容的类

    我不熟悉SuperCSV,但我认为当Expando或元类解决方案使用Groovy元对象协议时,它应该使用类似smth的反射

    GroovyShell(或GroovyClassLoader)将能够创建正常的类,并具有工作反射

    编辑:说明生成类的动态性质。我们首先创建类源代码(根据我们的需要,从运行时信息,从您的CSV头创建),然后使用它

    def createClassDeclaration()
    {
        String classDeclaration = "\nclass Test {\n"
        // Here you can use your runtime information, schema, array of fields, getted from any source.
        10.times {
            classDeclaration+="def field$it\n" // declares def field1, field2, ... etc
        }
        classDeclaration += """
        }
        return Test.class
        """
        println(classDeclaration)
        return classDeclaration
    }
    def compile(String s)
    {
        def c = (new GroovyShell().evaluate(s) as Class)
        def m = (c as Class).getMethod("setField1", [Object] as Class[])
        assert m
        println(c.methods.grep {it.name.startsWith("set")})
    
    }
    
    compile(createClassDeclaration())