Java注解可以做什么,不能做什么?

19

典型的用例是像@Override这样简单的东西,但显然您可以做更多的事情。如果你推动它们的极限,你会得到像Project Lombok这样的东西,尽管我的理解是这是对注解的滥用。那么您到底可以做什么?使用注解在编译时和运行时可以做哪些事情?有什么不能做的呢?


2
看Lombok很有趣,从@Data注释开始:“@ToString,@EqualsAndHashCode,@Getter在所有字段上,@Setter在所有非final字段上的快捷方式。您甚至可以获得一个免费的构造函数来初始化您的final字段!”如果您需要一个工具来自动生成所有字段的getter和setter,那么您的代码可能存在问题。 - Claudiu
@Claudiu:更不用说在所有非final字段上使用"@Setter"这种做法是完全错误的了。 - user319799
2
如果这样做是正确的,声明那些字段为公共字段。 - Claudiu
@Claudiu:不,你不需要这样做。至少在Java中不需要。这是非惯用语,并且如果您决定更改实现,则必须打破二进制兼容性。 - gustafc
@Claudiu:http://en.wikipedia.org/wiki/Object-oriented_programming 最值得一提的是“封装”部分;)尽管 Java 不容易传递干净的 OO 消息,但这不是故意破坏封装的理由;) - NoozNooz42
显示剩余3条评论
5个回答

6
我们使用运行时注解和反射来定制我们的领域模型映射到数据库。此外,我们在运行时使用代码中的注解进行表单验证。
另外,您可以使用Java附带的注解处理器预处理源文件。
编辑:如问题中所要求的lombok,增加了一种更强大的使用此注解处理的方式。让我简单描述一下:他们钩入了Java注解处理步骤:
1. Java编译器和 2. Eclipse IDE,在这里生成您的代码的解析树。
这样,Eclipse会显示更多您实际编写的代码,并且javac也认为是同样的情况。生成器技术使用旧式Java注解处理,但是您可以将Lombok视为使其真正有用的缺失粘合剂。

4

注解属于反射的范畴。仅有注解并不能提供任何功能,你需要在代码中使用它们,或者与诸如动态代理或字节码重写等反射领域的内容一起使用。

反射被认为是非常强大但同时也很危险的东西。

我认为根本问题是:“注解或更普遍地说反射有哪些合法的用途?”

由于反射和安全之间存在紧张关系(破坏类型系统,访问final字段等),因此有两个阵营:那些拥抱元编程的人和那些拥抱安全的人。什么是合法的最终取决于品味和观点。

相关问题:


根据您的评论,似乎您主要关心JSR-269和编译过程中的钩子。我看到JSR-269有两个用例:用于自定义错误/语义检查(例如Override),用于DSL/语言工程。除了用于黑客和实验之外,它是否被广泛使用,我不知道。以下是同事提供的一些很棒的链接:

话虽如此,我认为字节码转换/编译器钩子仍然属于元编程范畴。例如,你可以在编译时像Lombok一样生成getter/setter,或者在运行时使用动态代理来完成这个任务。因此,在我看来,这种二元性意味着我们仍然处在反射领域。


这是一个很好的观点,但注释也有相反的属性——它们可以将类型安全引入本来不具备类型安全的情况(例如当替代方案为XML配置时)。Google Guice就是这种类型注释使用的很好的例子。 - Yishai
1
我不同意你对根本问题的评估。我想知道通过编写注解处理器可以做哪些事情,而不是什么是“合法用途”,这也不是一个关于反射的问题。我只是想知道通过能够连接到编译处理器可以获得多少权力。我不是在问什么是良好的编程实践。 - swampsjohn
@swampsjohn 看起来你更关心编译时的注解,而不是运行时。我已经编辑了我的回答。 - ewernli

3

我相信您不能使用注解来洗衣服。

但除此之外,以下是我经验中注解的一些真实限制:

  1. 它们是静态的。这意味着您无法通过动态运行时配置替换它们。因此,如果您从注解中检索数据库信息,那可能非常有限。做到这一点的框架往往需要两种配置机制:注解和某些 XML 或其他动态机制。这并不完美。
  2. 与第 1 点相关,它们很难测试。想象一下必须处理某些注解的框架。创建所有变化以进行测试需要很多样板代码。
  3. 它们很难消费。反射陷阱和一般困难使得适合框架要求其用户编写注解,但您永远不希望框架的用户必须分析参数上的注解来确定任何内容。

1

注解是元数据,即关于代码的信息。

通过注解,您可以向注解的使用者(如编译器或运行时代码本身)提供提示和线索。我在一些场合仔细地使用它们,其中它们的存在替代了某些其他布尔比较评估为真的需要,并且提供的属性进一步说明了由于注解的存在实际上需要完成的工作。

关于注解的限制,我不确定如何回答。如果它们解决了实际问题或使您的代码更加优雅,请使用它们,但不要强制使用。

请原谅我可能过于简化事情。


请问您能否提供一个示例或链接,展示如何使用注解生成代码(就像在Project Lombok中看到的那样)? - Simon

0

这个问题非常(太?)宽泛,所以我只会给出一个我觉得有趣的例子。JPA 2.0 依赖于注解处理来为实体生成静态元模型类(用于使用 Criteria API 进行类型安全查询)。

另请参阅


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接