如何为 Java 注释提供符号?

How can I supply a symbol to a Java annotation?

看来是我的误解让我想到了这个问题。请帮我整理一下。 JLS 9.6.1 声明“Class 或 Class 的调用(§4.5)”作为注释类型涵盖,chrylis -cautiouslyoptimistic 指出。

我们都同意静态导入是一个常量(好吧,假装我没有说过那样的话:这当然不是真的)

import static path.to.someFunction

我创建了这样的注释

@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.METHOD, ElementType.FIELD})
public @interface Testing {
    Class<? extends Function> symbol();
}

给定一个静态函数(即使声明这个 final 也不会根据 Java 中的定义使 someFunction 常量,这让我很不爽):

public static Function<Long, Long> someFunction = a -> b;

不好意思(我知道函数本身和它的应用程序是有区别的),

public static Function<Long, Long> someFunction = a -> 2L;

我创建了这样的单元测试(假设前面提到的静态导入):

@Test
@Testing(symbol = someFunction)
void someFunctionTest() {
    ....
}

除了我的错误之外,有人认识到这在编译时会有多大用处吗?我可以在所有标有 @Tested 的函数上使用反射来查看是否确实在某处对其进行了测试(基于 @Testing 注释)。

有趣的是,我为注解提供了一个常量,但这是 IntelliJ 的抱怨:

Attribute value must be [a] constant.

这是怎么回事?注释机制是在尝试执行该函数,还是会接受它作为高阶函数?

你做不到as-is。 JLS 9.6.1:

The return type of a method declared in an annotation type must be one of the following, or a compile-time error occurs:

  • A primitive type
  • String
  • Class or an invocation of Class (§4.5)
  • An enum type
  • An annotation type
  • An array type whose component type is one of the preceding types (§10.1).

We all agree that a static import is a constant.

不,我们没有。

静态导入除了使 field/method/... 可以通过简单名称访问而不是必须使用完全限定名称之外什么都不做。

这个简单的名称可能是对常量字段的引用,也可能是对其他内容的引用。

您已将 someFunction 定义为

public static Function<Long, Long> someFunction = a -> b;

根据不是 a "constant expression" 的 Java 语言的规则(强调我的):

A constant expression is an expression denoting a value of primitive type or a String [...]

显然 Function 既不是原始值也不是 String

此外,您已将 symbol 定义为采用 Class<? extends Function>,这意味着您需要为其分配实现 Function 的 class。 someFunction 不是 Class,它是恰好实现 Function.

的实际对象

总体答案是,你不能这样做。由于多种原因,您的代码无法正常工作:

  • someFunction 不是编译时间常量
  • someFunction 不是 symbol 期望的 Class<? extends Function>
  • 不支持实际类型 Function<?,?> 作为注释中的属性类型。