【发布时间】:2018-11-21 09:36:56
【问题描述】:
我已经开发了一个框架和相应的 API,其中包括一个运行时可见的注释。 API 还提供了一些帮助方法,供客户端在其类具有该注释的对象上使用。可以理解,助手与注解紧密耦合,但重要的是它们的内部被客户端封装。辅助方法目前通过注解类型中的静态内部类提供...
@Target(TYPE)
@Retention(RUNTIME)
public @interface MyAnnotation {
// ... annotation elements, e.g. `int xyz();` ...
public static final class Introspection {
public static Foo helper(Object mightHaveMyAnnotation) {
/* ... uses MyAnnotation.xyz() if annotation is present ... */
}
}
}
...但是助手可以很容易地存在于其他一些顶级实用程序类中。无论哪种方式都可以从客户端代码中提供必要的封装量,但都会产生额外的成本来维护一个完全独立的类型,阻止它们实例化,因为所有有用的方法都是静态的,等等。
当 Java 8 在 Java 接口类型上引入静态方法时(请参阅 JLS 9.4),该功能被吹捧为提供...的能力...
... 在你的库中组织辅助方法;您可以将特定于接口的静态方法保留在同一接口中,而不是在单独的类中。
——来自 Java 教程 Interface Default Methods
这已在 JDK 库中用于提供诸如 List.of(...)、Set.of(...) 等的实现,而以前此类方法被归入一个单独的实用程序类,例如 java.util.Collections。通过在其相关接口中定位实用程序方法,它improves their discoverability 并从 API 域中删除了可能不必要的辅助类类型。
由于我当前用于注解类型的JVM bytecode representation与普通接口密切相关,我想知道注解是否也支持静态方法。当我将助手移动到注释类型中时,例如:
@Target(TYPE)
@Retention(RUNTIME)
public @interface MyAnnotation {
// ... annotation elements ...
public static Foo helper(Object mightHaveMyAnnotation) { /* ... */ }
}
... javac 抱怨以下编译时错误让我有点惊讶:
OpenJDK 运行时环境 18.3(内部版本 10+46)
- 此处不允许使用静态修饰符
- 注解类型声明中的元素不能声明形参
- 接口抽象方法不能有主体
显然,Java 语言目前不允许这样做。可能有很好的设计理由来禁止它,或者像 previously presumed 对于静态接口方法一样,“没有令人信服的理由这样做;一致性不足以改变现状”。
这个问题的具体目标不是问“为什么它不起作用?”或“应该语言支持吗?”,以避免基于意见的答案。
JVM 是一种强大的技术,在许多方面比 Java 语言所允许的更灵活。与此同时,Java 语言也在不断发展,今天的答案明天可能就过时了。理解必须非常小心地使用这种力量......
在技术上是否可以将静态行为直接封装在注解类型中?如何实现?
【问题讨论】:
-
这似乎不是问题,这个问题的唯一理由是通过接口和注释的比较(类似于“接口和抽象类之间的差异”)。尽管 JVM 可能支持它,但您的回答(在您的编辑之前)是有偏见的并且没有解释 为什么 它应该被支持,而是它是可能的。这似乎是一个 XY 问题,因为它没有说明 why 对象需要通过注释来命名,因此我们无法建议适当的解决方法。
标签: java annotations jvm static-methods jls