【问题标题】:How can I supply a symbol to a Java annotation? [duplicate]如何为 Java 注释提供符号? [复制]
【发布时间】:2020-09-02 08:29:07
【问题描述】:

看来我的误解导致我提出这个问题。请帮我整理一下。 JLS 9.6.1 声明“类或类的调用(第 4.5 节)”作为注释类型被涵盖,chrylis -cautiouslyoptimistic 指出。

我们都同意静态导入是一个常量(好吧,假装我没有说那句话:这当然不是真的https://stackoverflow.com/a/9083023/1236128

import static path.to.someFunction

我创建一个这样的注释

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

给定一个静态函数(即使声明这个 final 也不会使 someFunction 在 Java 中定义为常量,这让我很失望):

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 给出的抱怨:

属性值必须是 [a] 常量。

那是怎么回事?注释机制是在尝试执行函数,还是将其作为高阶函数接受?

【问题讨论】:

标签: java annotations


【解决方案1】:

我们都同意静态导入是一个常量。

不,我们没有。

静态导入除了使字段/方法/...可通过简单名称访问之外没有任何作用,而不必使用完全限定名称。

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

您已将someFunction 定义为

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

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

常量表达式是表示原始类型或字符串 [...]

的值的表达式

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

此外,您已将symbol 定义为采用Class&lt;? extends Function&gt;,这意味着您需要为其分配一个实现Function 的类。 someFunction 不是Class,它是一个碰巧实现Function 的实际对象。

【讨论】:

  • final 应用于我对someFunction 的定义有什么好处吗?我很难接受someFunction 不是一个常数。就像我将其定义为 a-&gt;2.
  • @JonathanKomar:应用final 会将类型更改为原始类型还是String?它会将字段从Function 更改为Class&lt;? extends Function&gt;。简而言之,lambdas 不会给你一个Class&lt;? extends Function&gt;,他们只能给你一个Function,所以你不能在你的注释中使用 lambdas。
  • 好吧,还有几件事要补充:我虽然 Function 是一门课。我想someFunction 的应用将是一个常数。这会包含在 Java 的定义中吗:Function&lt;Long, Long&gt; someFunction = a -&gt; 2L?输出可以被拆箱成一个原语......
  • @JonathanKomar Function 一个类。你没有传递Function.class,你试图传递Function的实例
【解决方案2】:

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

  • someFunction 不是编译时常量
  • someFunction 不是 Class&lt;? extends Function&gt;,正如 symbol 所期望的那样
  • 实际类型 Function&lt;?,?&gt; 不支持作为注释中的属性类型。

【讨论】:

  • 我的理解是静态函数一个编译时常量。 Function&lt;?,?&gt; 类型不是告诉编译器对 Function?, ? 进行类型检查的一种方式吗?
  • Java 中的“常量表达式”有一个非常明确的定义,并且只能应用于原始值或String 值。
  • @luk2302 哇,那个帖子很有帮助。 msi 的回答真的一针见血,我很容易认为我的问题是我对 Java 中的 constant 的误解造成的。
【解决方案3】:

你不能照原样做。 JLS 9.6.1:

注解类型中声明的方法的返回类型必须是以下之一,否则会发生编译时错误:

  • 原始类型
  • 字符串
  • 类或类的调用(第 4.5 节)
  • 枚举类型
  • 注释类型
  • 一种数组类型,其组件类型是上述类型之一 (§10.1)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 2012-05-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多