在 Java 中生成 getter/setter(再次)
我正在考虑编写方法
class MyClass {
@Get
@Set
protected int aValue;
}
,然后自动为该类生成 get_aValue() 和 set_AValue() 方法。
我发现了这些可能性:
1a)在编译时。使用注释处理器单独处理 MyClass.java,然后编写一个新的 MyClass.java,最后将后者(替换原来的)与 .java 的其余部分一起使用
1b) 在编译时。使用注释处理器生成一个 MyClassGeneerated.java 文件,其中包含一个新类(带有 get/set 方法),该新类是原始 MyClass 的子类。
2) 在运行时。使用 java.lang.instrument 和外部工具(如 BCEL)在 MyClass.class 中编写新代码。
好吧,问题是:考虑到尽可能我不想使用第三方库(如 lombok 项目或 BCEL)
a)我是否缺少任何其他方法?
b) 您会使用哪种方法?
我想我会使用1a),因为
1b)不干净(程序的其余部分应该使用MyClassGeneradted而不是原来的MyClass,尽管也许这只是名称问题)
2)真的很困难(对我来说,至少)。
I'm considering the approaches to write
class MyClass {
@Get
@Set
protected int aValue;
}
and then, automatically, generate get_aValue() and set_AValue() methods for the class.
I've found these possibilities:
1a) At compile time. Use an annotation processor for separately processing MyClass.java, then write a new MyClass.java, and finally use this latter (substituting the original) with the rest of .java
1b) At compile time. Use an annotation processor to generate a MyClassGenerated.java file with a new class (with the get/set methods) being this one a sub-class of the original MyClass.
2) At run time. Use java.lang.instrument and an external tool (like BCEL) to weave new code in MyClass.class.
Well, the questions are: considering that as far as possible I don't want to use third party libraries (like the lombok project or BCEL)
a) Am I missing any other approach?
b) Which approach would you use?
I guess I will use 1a) because
1b) is not clean (the rest of the program should use MyClassGeneradted instead of the original MyClass, although perhaps it's only a matter of names)
2) is really difficult (for me, at least).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
听起来只是为了生成 getter 和 setter 方法就需要做很多工作。为什么不直接使用 eclipse getter 和 setter 生成器:
(来源:eclipse-blog.org< /a>)
That sounds like a lot of work just to generate getter and setter methods. Why not just use eclipses getter and setter generator:
(source: eclipse-blog.org)
你错过了一些东西,如果你想走这条路,我想说这是最好的方法:
1c)在编译时。正常编译该类,然后使用 APT 注释处理器修改 .class 文件(不是源文件)以向字节码添加适当的 get 和 set 方法。
这样,您的源代码将保持原始状态,您不必为临时文件而烦恼,并且实际编译的类正是您想要的那样。
尽管如此,这仍然是用大锤打开螺母。这是可行的,但现在您的代码并不是严格意义上的 Java,因为如果有人获取它并在其上运行 javac,他们将得到一个没有 getter 和 setter 的类。这将使调试变得困难,因为所有行号都会混乱,除非您非常确定您使用注释处理器做了正确的事情,否则您甚至无法看到 getter 和 setter 的来源纠正错误。静态分析工具会告诉您该属性从未被使用过,等等。
我同意一般共识 - 只需使用每个 IDE 为您提供的方法在源文件中生成它们即可。这几乎比编写注释花费更多的时间,并且每个开发人员和工具都可以理解。 Java 没有属性——别介意它。 :-)
You are missing something, which I'd say is the best approach if you want to go down this route:
1c) At compile time. Compile the class as normal, then use an APT annotation processor to modify the .class file (not the source file) to add the appropriate get and set methods to the bytecode.
This way your source stays pristine, you don't have to faff about with temporary files, and the actual compiled class is exactly as you want it to be.
Still, this is using a sledgehammer to open a nut. It's do-able, but now your code isn't strictly Java in the sense that if someone takes it and runs
javac
on it, they'll get a class without getters and setters. This will make debugging difficult as all the line numbers will be messed up, and unless you're very sure you've done the right thing with your annotation processor, you won't even be able to see the source of the getters and setters to correct mistakes. Static analysis tools will tell you that the attribute is never used, etc.I'm with the general consensus - just generate them in the source file using the methods that every IDE gives you. This takes barely any more time than writing annotations, and is understood by every developer and tool out there. Java doesn't have properties - get over it. :-)
实际上,我通常使用方法 3 - 我只是对字段进行编码并使用 eclipse IDE 自动生成 getter 和 setter 方法。 (netbeans 和 IntelliJ 应该具有类似的功能)
使用 IDE 的自动生成工具,您甚至可以定义生成的 getter/setter 方法的可见性(您可能希望将 setter 可见性限制为私有),或者如果您需要额外的代码,则编辑模板方法体。
Practically spoken, I usually use approach 3 - I just code the fields and use eclipse IDE to autogenerate getter and setter methods. (netbeans and IntelliJ should have similiar features)
With the IDE's autogeneration tools you can even define the visibility of the generated getter/setter methods (you might want to limit the setters visibility to private) or edit the template if you need additional code the the method bodies.
Project Lombok 几乎正是您想要的,尽管实现有所不同。
Project Lombok is pretty much exactly what you want, although the implementation differs.
(兼容Java)支持
b
真的,如果你感到语言的痛苦并且不想使用像字节码编织器或外部库这样的拐杖,你应该寻找更绿色的牧场。
(compatible to Java) that supports
that
Seriously, if you feel the pain of the language and don't want to use crutches like byte code weavers or external libs, you should look for greener pastures.
我不知道为什么没有建议另一个明显的选择,但我会考虑另一种方法,您只需定义接口,并使用一个库来实现指定的 setter、getter 和所需的内部字段。
所以你可以指定类似
public interface Bean {
公共 int getX();
公共无效setX(int值);
并
要求库为此实例化类型(也许还有创建类型实例的便捷方法)。如果有必要,注释可以用于进一步配置(如果需要),但对于 get/set 样式 bean 则并非如此。
这与你的(2)不同,除非我遗漏了一些东西,否则它不会按原样工作:事情是,你必须在编译期间拥有可用的方法。这就是使用接口可以解决的问题。需要生成代码,但可以自动化。
我希望这样的库存在,但如果不存在,使用字节码生成库(asm、cglib、janino、javassist 等)编写通用库应该是完全可行的。
为简单的用例编写这样的库当然是重量级的,但使用它似乎是有意义的。
...很可能使用 IDE 来解决您遇到的具体情况(无论是什么)是最简单的。 :-)
I don't know why another obvious choice hasn't been suggested, but I would consider another approach, where you just define interfaces, and use a library that implements specified setters, getters, and internal fields needed.
So you would specify something like
public interface Bean {
public int getX();
public void setX(int value);
}
and ask library to instantiate type for that (and maybe convenience methods for creating instances of type). If necessary, annotations could be used for further configuration if necessary, but for get/set style beans that is not the case.
This is different from your (2), which would not work as is unless I am missing something: thing is, you must have methods available during compilation time. And that is what using interfaces would solve. Code generation would be needed but could be automated.
I would expect such libraries to exist, but if not, writing general-purpose one should be quite doable using byte code generation libs (asm, cglib, janino, javassist, whatever).
Writing such lib for simple use case is heavy-weight of course, but using one would seem to make sense.
... and it may well be that using an IDE would be easiest to solve specific case you have, whatever it is. :-)