java 自动生成Java源代码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5745721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Automatically generating Java source code
提问by Tony the Pony
I'm looking for a way to automatically generate source code for new methods within an existing Java source code file, based on the fields defined within the class.
我正在寻找一种根据类中定义的字段为现有 Java 源代码文件中的新方法自动生成源代码的方法。
In essence, I'm looking to execute the following steps:
实质上,我希望执行以下步骤:
- Read and parse
SomeClass.java
- Iterate through all fields defined in the source code
- Add source code method
someMethod()
- Save
SomeClass.java
(Ideally, preserving the formatting of the existing code)
- 读取和解析
SomeClass.java
- 遍历源代码中定义的所有字段
- 添加源代码方法
someMethod()
- 保存
SomeClass.java
(理想情况下,保留现有代码的格式)
What tools and techniques are best suited to accomplish this?
哪些工具和技术最适合实现这一目标?
EDIT
编辑
I don't want to generate code at runtime; I want to augment existing Java source code
我不想在运行时生成代码;我想扩充现有的 Java源代码
采纳答案by kdabir
Modifying the same java source file with auto-generated code is maintenance nightmare. Consider generating a new class that extends you current class and adds the desired method. Use reflection to read from user-defined class and create velocity templates for the auto-generating classes. Then for each user-defined class generate its extending class. Integrate the code generation phase in your build lifecycle.
使用自动生成的代码修改同一个 java 源文件是维护的噩梦。考虑生成一个新类来扩展您当前的类并添加所需的方法。使用反射从用户定义的类中读取并为自动生成的类创建速度模板。然后为每个用户定义的类生成其扩展类。将代码生成阶段集成到您的构建生命周期中。
Or you may use 'bytecode enhancement' techniques to enhance the classes without having to modify the source code.
或者您可以使用“字节码增强”技术来增强类而无需修改源代码。
Updates:
更新:
- mixing auto-generated code always pose a risk of someone modifying it in future to just to tweak a small behavior. It's just the matter of next build, when this changes will be lost.
- you will have to solely rely on the comments on top of auto-generated source to prevent developers from doing so.
- version-controlling - Lets say you update the template of someMethod(), now all of your source file's version will be updated, even if the source updates is auto-generated. you will see redundant history.
- 混合自动生成的代码总是会带来将来有人修改它只是为了调整一个小行为的风险。这只是下一次构建的问题,当这些更改将丢失时。
- 您将不得不完全依赖自动生成的源代码之上的注释来防止开发人员这样做。
- 版本控制 - 假设您更新 someMethod() 的模板,现在所有源文件的版本都将更新,即使源更新是自动生成的。你会看到多余的历史。
回答by Ira Baxter
What you want is a Program Transformationsystem.
你想要的是一个程序转换系统。
Good ones have parsers for the language you care about, build ASTs representing the program for the parsed code, provide you with access to the AST for analaysis and modification, and can regenerate source text from the AST. Your remark about "scanning the fields" is just a kind of traversal of the AST representing the program. For each interesting analysis result you produce, you want to make a change to the AST, perhaps somewhere else, but nonetheless in the AST. And after all the chagnes are made, you want to regenerate text with comments (as originally entered, or as you have constructed in your new code).
好的有你关心的语言的解析器,为解析的代码构建代表程序的 AST,为你提供对 AST 的访问以进行分析和修改,并且可以从 AST 重新生成源文本。你所说的“扫描字段”只是对代表程序的AST的一种遍历。对于您产生的每一个有趣的分析结果,您都希望对 AST 进行更改,也许在其他地方,但仍然在 AST 中。在完成所有更改之后,您希望重新生成带有注释的文本(如最初输入的那样,或者如您在新代码中构建的那样)。
There are several tools that do this specifically for Java.
有几种工具专门针对 Java 执行此操作。
Hymanpotprovides a parser, builds ASTs, and lets you code Java procedures to do what you want with the trees. Upside: easy conceptually. Downside: you write a lot more Java code to climb around/hack at trees than you'd expect. Hymanpot only works with Java.
Hymanpot提供了一个解析器,构建了 AST,并允许您编写 Java 过程代码以对树执行您想要的操作。好处:概念上很容易。缺点:您编写的 Java 代码比您预期的要多得多。Hymanpot 仅适用于 Java。
Strategoand TXLparse your code, build ASTs, and let you write "surce-to-source" transformations (using the syntax of the target language, e.g., Java in this case) to express patterns and fixes. Additional good news: you can define any programming language you like, as the target language to be processed, and both of these have Java definitions. But they are weak on analysis: often you need symbol tables, and data flow analysis, to really make analyses and changes you need. And they insist that everythingis a rewrite rule, whether that helps you or not; this is a little like insisting you only need a hammer in toolbox; after all, everything can be treated like a nail, right?
Stratego和TXL解析您的代码,构建 AST,并让您编写“源到源”转换(使用目标语言的语法,例如在本例中为 Java)来表达模式和修复。额外的好消息:您可以定义任何您喜欢的编程语言,作为要处理的目标语言,并且这两种语言都有 Java 定义。但是他们在分析方面很弱:通常你需要符号表和数据流分析,才能真正进行你需要的分析和更改。他们坚持认为一切都是重写规则,不管这对你有没有帮助;这有点像坚持在工具箱中只需要一把锤子;毕竟,一切都可以像钉子一样对待,对吗?
Our DMS Software Reengineering Toolkitallows the definition of an abitrary target language (and has many predefined langauges including Java), includes all the source-to-source transformation capabilities of Stratego, TXL, the procedural capability of Hymanpot, and additionally provides symbol tables, control and data flow analysis information. The compiler guys taught us these things were necessary to build strong compilers (= "analysis + optimizations + refinement") and it is true of code generation systems too, for exactly the same reasons. Using this approach you can generate code and optimize it to the extent you have the knowledge to do so. One example, similar to your serialization ideas, is to generate fast XML readers and writers for specified XML DTDs; we've done that with DMS for Java and COBOL.
我们的DMS 软件再工程工具包允许定义任意目标语言(并且有许多预定义的语言,包括 Java),包括Stratego、TXL的所有源到源转换能力,Hymanpot的程序能力,另外提供符号表、控制和数据流分析信息。编译器的人告诉我们这些东西对于构建强大的编译器(=“分析+优化+细化”)是必要的,代码生成系统也是如此,出于完全相同的原因。使用这种方法,您可以生成代码并在您有知识的范围内对其进行优化。一个与您的序列化想法类似的示例是为指定的 XML DTD 生成快速的 XML 读取器和写入器;我们已经使用 DMS for Java 和 COBOL 做到了这一点。
DMS has been used to read/modify/write many kinds of source files. A nice example that will make the ideas clear can be found in this technical paper, which shows how to modify code to insert instrumentation probes: Branch Coverage Made Easy. A simpler, but more complete example of defining an arbitrary lanauges and transformations to apply to it can be found at How to transform Algebrausing the same ideas.
DMS 已被用于读取/修改/写入多种源文件。可以在这篇技术论文中找到一个很好的例子,可以让这些想法变得清晰,它展示了如何修改代码以插入检测探针: Branch Coverage Made Easy。一个更简单但更完整的定义任意语言和变换的示例可以在如何使用相同的想法变换代数中找到。
回答by SamG
Have a look at Java Emitter Templates. They allow you to create java source files by using a mark up language. It is similar to how you can use a scripting language to spit out HTML except you spit out compilable source code. The syntax for JET is very similar to JSP and so isn't too tricky to pick up. However this may be an overkill for what you're trying to accomplish. Here are some resources if you decide to go down that path:
看看Java 发射器模板。它们允许您使用标记语言创建 Java 源文件。它类似于您如何使用脚本语言来输出 HTML,只是您输出的是可编译的源代码。JET 的语法与 JSP 非常相似,因此不会太难掌握。但是,这对于您要完成的工作来说可能是一种矫枉过正。如果您决定走这条路,这里有一些资源:
回答by CPerkins
Iterating through the fields and defining someMethod is a pretty vague problem statement, so it's hard to give you a very useful answer, but Eclipse's refactoring support provides some excellent tools. It'll give you constructors which initialize a selected set of the defined members, and it'll also define a toString method for you.
遍历字段并定义 someMethod 是一个非常模糊的问题陈述,因此很难给您一个非常有用的答案,但是 Eclipse 的重构支持提供了一些出色的工具。它将为您提供初始化一组选定的已定义成员的构造函数,它还将为您定义一个 toString 方法。
I don't know what other someMethod()'s you'd want to consider, but there's a start for you.
我不知道您还想考虑哪些其他 someMethod(),但是您已经有了一个开始。
回答by Wyzard
I'd be very wary of injecting generated code into files containing hand-written code. Hand-written code should be checked into revision control, but generated code should not be; the code generation should be done as part of the build process. You'd have to structure your build process so that for each file you make a temporary copy, inject the generated source code into it, and compile the result, without touching the original source file that the developers work on.
我会非常谨慎地将生成的代码注入包含手写代码的文件中。手写代码应该被签入版本控制,但生成的代码不应该被签入;代码生成应该作为构建过程的一部分来完成。您必须构建构建过程,以便为每个文件制作一个临时副本,将生成的源代码注入其中,然后编译结果,而无需触及开发人员正在处理的原始源文件。