如何向Java注解提供一个符号?

huangapple go评论71阅读模式
英文:

How can I supply a symbol to a Java annotation?

问题

以下是翻译好的内容:

看起来我的误解导致了我提出这个问题。请帮我梳理一下。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报错:

属性值必须是常量。

这是怎么回事?注解机制是试图执行该函数,还是会将其视为高阶函数?

英文:

It looks like my misconceptions have led me to this question. Please help me sort them out. JLS 9.6.1 states that "Class or an invocation of Class (§4.5)" is covered as an annotation type, chrylis -cautiouslyoptimistic pointed out.

We all agree that a static import is a constant (well, pretend I did not make that statement: It is of course not true https://stackoverflow.com/a/9083023/1236128)

import static path.to.someFunction

I create an annotation like this

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

Given a static function (even declaring this final does not make someFunction constant by definition in Java, which is throwing me off):

public static Function&lt;Long, Long&gt; someFunction = a -&gt; b;

Excuse me (I realize there is a difference between the function itself and its application),

public static Function&lt;Long, Long&gt; someFunction = a -&gt; 2L;

I create a unit test like this (assuming the aforementioned static import):

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

Aside from my mistakes, does anybody recognize how useful this would be at compile time? I could use reflection on all functions marked with say @Tested to see whether there is indeed a test for it somewhere (on the basis of the @Testing annotation).

The funny thing is, I am supplying the annotation with a constant, but that is the complaint given by IntelliJ:

> Attribute value must be [a] constant.

What's up with that? Is the annotation mechanism trying to execute the function, or will it accept it as a higher order function?

答案1

得分: 1

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

不,我们并不同意。

静态导入除了使字段/方法/...能够通过简单名称访问外,什么都不做,而不必使用完全限定的名称。

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

你已经将 someFunction 定义为

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

根据Java语言的规则,这不是 一个“常量表达式”(我强调):

> 常量表达式是表示原始类型或String值的表达式[...]

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

另外,你已经将 symbol 定义为接受 Class<? extends Function>,这意味着你需要为它分配一个实现了 Function 的类。someFunction 不是一个 Class,它是一个实际实现了 Function 的对象。

英文:

> We all agree that a static import is a constant.

No, we don't.

A static import does nothing other than making a field/method/... accessible via a simple name as opposed to having to use the fully qualified name.

That simple name might be a reference to a constant field or it might be a reference to something else.

You've defined someFunction as

public static Function&lt;Long, Long&gt; someFunction = a -&gt; b;

According to the rules of the Java language that is not a "constant expression" (emphasis mine):

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

Obviously a Function is neither a primitive value nor a String.

Additionally you've defined the symbol to take a Class&lt;? extends Function&gt;, which means you need to assign it a class that implements Function. someFunction is not a Class, it's an actual object that happens to implement Function.

答案2

得分: 1

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

  • someFunction 不是编译时常量
  • someFunction 不是 Class&lt;? extends Function&gt;,而 symbol 需要的是这个类型
  • 实际类型 Function&lt;?,?&gt; 在注解中不被支持作为属性类型。
英文:

The overall answer is no, you cannot do this. And your code does not work for a multitude of reasons:

  • someFunction is not a compile time constant
  • someFunction is not a Class&lt;? extends Function&gt; as symbol expects
  • the actual type Function&lt;?,?&gt; is not supported as an attribute type in annotations.

答案3

得分: 0

你不能按原样执行此操作。JLS 9.6.1:

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

  • 原始类型
  • String
  • Class 或 Class 的调用(§4.5)
  • 枚举类型
  • 注解类型
  • 其组件类型为前述类型之一的数组类型(§10.1)。
英文:

You can't do it 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).

huangapple
  • 本文由 发表于 2020年9月2日 16:29:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/63701623.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定