用于生成Java源文件的Java API

用于生成Java源文件的Java API,java,eclipse,code-generation,Java,Eclipse,Code Generation,我正在寻找一个生成Java源文件的框架 类似于以下API: X clazz = Something.createClass("package name", "class name"); clazz.addSuperInterface("interface name"); clazz.addMethod("method name", returnType, argumentTypes, ...); File targetDir = ...; clazz.generate(targetDir);

我正在寻找一个生成Java源文件的框架

类似于以下API:

X clazz = Something.createClass("package name", "class name");
clazz.addSuperInterface("interface name");
clazz.addMethod("method name", returnType, argumentTypes, ...);

File targetDir = ...;
clazz.generate(targetDir);
然后,应该在目标目录的子目录中找到java源文件

有人知道这样一个框架吗


编辑

  • 我真的需要源文件
  • 我还想填写方法的代码
  • 我在寻找一个高级抽象,而不是直接的字节码操作/生成
  • 我还需要对象树中的“类结构”
  • 问题域是一般性的:生成大量非常不同的类,而没有“公共结构”

  • 解决方案
    我已经在你的答案中发布了2个答案。。。和


    我在我的解决方案中使用了:-)

    如果您真的需要源代码,我不知道任何生成源代码的东西。但是,您可以使用或直接创建.class文件


    您可能可以从这些代码生成源代码,但我只使用它们生成字节码。

    该项目可用于生成源代码。我不认为它的API与您描述的完全一样,但每次我听说一个项目进行Java源代码生成时,他们都使用JET或一个自制工具。

    我自己是为了一个模拟生成器工具而做的。这是一项非常简单的任务,即使您需要遵循Sun的格式化准则。我打赌你会更快地完成代码,然后在互联网上找到符合你目标的东西


    您基本上已经自己概述了API。现在就用实际代码填充它

    另一种选择是EclipseJDT的AST,如果您需要重写任意Java源代码,而不仅仅是生成源代码,它是很好的选择。
    (我相信它可以独立于eclipse使用)。

    我不知道有什么库,但您可能只需要一个通用模板引擎。还有,我个人对

    有很好的经验,Sun提供了一个名为CodeModel的API,用于使用API生成Java源文件。这不是最容易获得信息的事情,但它就在那里,而且工作得非常好

    获取它的最简单方法是作为JAXB 2 RI的一部分—java生成器的XJC模式使用CodeModel生成其java源代码,它是XJC JAR的一部分。您可以将其仅用于代码模型


    从使用CodeModel找到的解决方案中获取它 谢谢

    例如,使用此代码:

    JCodeModel cm = new JCodeModel();
    JDefinedClass dc = cm._class("foo.Bar");
    JMethod m = dc.method(0, int.class, "foo");
    m.body()._return(JExpr.lit(5));
    
    File file = new File("./target/classes");
    file.mkdirs();
    cm.build(file);
    
    AST ast = AST.newAST(AST.JLS3);
    CompilationUnit cu = ast.newCompilationUnit();
    
    PackageDeclaration p1 = ast.newPackageDeclaration();
    p1.setName(ast.newSimpleName("foo"));
    cu.setPackage(p1);
    
    ImportDeclaration id = ast.newImportDeclaration();
    id.setName(ast.newName(new String[] { "java", "util", "Set" }));
    cu.imports().add(id);
    
    TypeDeclaration td = ast.newTypeDeclaration();
    td.setName(ast.newSimpleName("Foo"));
    TypeParameter tp = ast.newTypeParameter();
    tp.setName(ast.newSimpleName("X"));
    td.typeParameters().add(tp);
    cu.types().add(td);
    
    MethodDeclaration md = ast.newMethodDeclaration();
    td.bodyDeclarations().add(md);
    
    Block block = ast.newBlock();
    md.setBody(block);
    
    MethodInvocation mi = ast.newMethodInvocation();
    mi.setName(ast.newSimpleName("x"));
    
    ExpressionStatement e = ast.newExpressionStatement(mi);
    block.statements().add(e);
    
    System.out.println(cu);
    
    我可以得到以下输出:

    package foo;
    public class Bar {
        int foo() {
            return  5;
        }
    }
    
    package foo;
    import java.util.Set;
    class Foo<X> {
      void MISSING(){
        x();
      }
    }
    

    通过Eclipse JDT的AST找到解决方案
    谢谢

    例如,使用此代码:

    JCodeModel cm = new JCodeModel();
    JDefinedClass dc = cm._class("foo.Bar");
    JMethod m = dc.method(0, int.class, "foo");
    m.body()._return(JExpr.lit(5));
    
    File file = new File("./target/classes");
    file.mkdirs();
    cm.build(file);
    
    AST ast = AST.newAST(AST.JLS3);
    CompilationUnit cu = ast.newCompilationUnit();
    
    PackageDeclaration p1 = ast.newPackageDeclaration();
    p1.setName(ast.newSimpleName("foo"));
    cu.setPackage(p1);
    
    ImportDeclaration id = ast.newImportDeclaration();
    id.setName(ast.newName(new String[] { "java", "util", "Set" }));
    cu.imports().add(id);
    
    TypeDeclaration td = ast.newTypeDeclaration();
    td.setName(ast.newSimpleName("Foo"));
    TypeParameter tp = ast.newTypeParameter();
    tp.setName(ast.newSimpleName("X"));
    td.typeParameters().add(tp);
    cu.types().add(td);
    
    MethodDeclaration md = ast.newMethodDeclaration();
    td.bodyDeclarations().add(md);
    
    Block block = ast.newBlock();
    md.setBody(block);
    
    MethodInvocation mi = ast.newMethodInvocation();
    mi.setName(ast.newSimpleName("x"));
    
    ExpressionStatement e = ast.newExpressionStatement(mi);
    block.statements().add(e);
    
    System.out.println(cu);
    
    我可以得到以下输出:

    package foo;
    public class Bar {
        int foo() {
            return  5;
        }
    }
    
    package foo;
    import java.util.Set;
    class Foo<X> {
      void MISSING(){
        x();
      }
    }
    
    package-foo;
    导入java.util.Set;
    福班{
    void缺失(){
    x();
    }
    }
    
    还有。它由ANTLR的作者编写,功能非常强大。

    这取决于你想做什么。代码生成本身就是一个主题。如果没有特定的用例,我建议查看velocity代码生成/模板库。另外,如果您离线生成代码,我建议使用ArgoUML之类的工具从UML图/对象模型转换为Java代码。

    我构建了一个非常类似于您理论上的DSL的工具,称为“sourcegen”,但从技术上讲,它不是我编写的ORM的UTI项目。DSL看起来像:

    @Test
    public void testTwoMethods() {
        GClass gc = new GClass("foo.bar.Foo");
    
        GMethod hello = gc.getMethod("hello");
        hello.arguments("String foo");
        hello.setBody("return 'Hi' + foo;");
    
        GMethod goodbye = gc.getMethod("goodbye");
        goodbye.arguments("String foo");
        goodbye.setBody("return 'Bye' + foo;");
    
        Assert.assertEquals(
        Join.lines(new Object[] {
            "package foo.bar;",
            "",
            "public class Foo {",
            "",
            "    public void hello(String foo) {",
            "        return \"Hi\" + foo;",
            "    }",
            "",
            "    public void goodbye(String foo) {",
            "        return \"Bye\" + foo;",
            "    }",
            "",
            "}",
            "" }),
        gc.toCode());
    }
    

    它还做了一些整洁的事情,比如“自动组织导入”参数/返回类型中的任何FQCN,自动修剪此codegen运行中未触及的任何旧文件,正确缩进内部类,等等

    其思想是生成的代码应该看起来很漂亮,没有警告(未使用的导入等),就像代码的其余部分一样。这么多生成的代码读起来很难看…太可怕了

    无论如何,文档并不多,但我认为API非常简单/直观。如果有人感兴趣,Maven回购协议是有效的。

    示例: 1/

    二,/

    有一个新项目。基于模板的代码生成器。您可以使用编写自定义模板,并根据java反射生成文件。这是生成任何文件的最简单方法。您可以通过生成AspectJ文件、基于JPA注释的SQL、基于枚举的插入/更新等来生成getter/settest/toString

    模板示例:

    package ${cls.package.name};
    
    public class ${cls.shortName}Builder {
    
        public static ${cls.name}Builder builder() {
            return new ${cls.name}Builder();
        }
    <% for(field in cls.fields) {%>
        private ${field.type.name} ${field.name};
    <% } %>
    <% for(field in cls.fields) {%>
        public ${cls.name}Builder ${field.name}(${field.type.name} ${field.name}) {
            this.${field.name} = ${field.name};
            return this;
        }
    <% } %>
        public ${cls.name} build() {
            final ${cls.name} data = new ${cls.name}();
    <% for(field in cls.fields) {%>
            data.${field.setter.name}(this.${field.name});
    <% } %>
            return data;
        }
    }
    
    package${cls.package.name};
    公共类${cls.shortName}Builder{
    公共静态${cls.name}Builder(){
    返回新的${cls.name}Builder();
    }
    私有${field.type.name}${field.name};
    public${cls.name}Builder${field.name}(${field.type.name}${field.name}){
    这个${field.name}=${field.name};
    归还这个;
    }
    public${cls.name}build(){
    final${cls.name}data=new${cls.name}();
    data.${field.setter.name}(this.${field.name});
    返回数据;
    }
    }
    
    您可以使用Roaster()生成代码

    以下是一个例子:

    JavaClassSource source = Roaster.create(JavaClassSource.class);
    source.setName("MyClass").setPublic();
    source.addMethod().setName("testMethod").setPrivate().setBody("return null;")
               .setReturnType(String.class).addAnnotation(MyAnnotation.class);
    System.out.println(source);
    
    将显示以下输出:

    public class MyClass {
       private String testMethod() {
           return null;
       }
    }
    

    下面是一个JSON到POJO的项目,看起来很有趣:


    你的问题非常笼统,你的问题领域真的如此笼统吗?你能更具体地说明你的问题领域吗?例如,我编写了代码生成工具来生成特定问题的代码,如消除重复的异常类代码,或消除枚举中的重复。@Vlookward:您可以将问题中的答案作为下面两个单独的答案移动。然后在每个问题上添加一个链接。@Banengusk:谢谢你的提问,节省了我搜索互联网最黑暗部分的时间@Skffman:伟大的发现-你让另一个开发人员在他即将到来的任务中更加轻松:)这样的回答解决了C++的问题,而不是java,但是答案也适用于java。呵呵。。。如果没有找到框架,那么我将编写它。我希望有很多功能,所以我不会在一个上午得到它…太好了!!一个抽象的语法树就是我要找的。。。现在