如何访问接收器类型参数的类型注释

18

我正在查看一个相当琐碎的类,它具有定义了一个带注释的接收方类型的单个方法:

class Foo<T> { 
  void foo(Foo<@Bar T> this) {}
}

我现在想访问接收器类型参数上的类型注释@Bar,但Java反射API在访问接收器时返回一个带注释的原始类型:

assert Foo.class.getDeclaredMethod("foo")
                .getAnnotatedReceiverType() 
  instanceof AnnotatedParameterizedType;
断言失败,因为返回的注释类型是作为原始类型Foo返回的。这是有意的吗?当访问返回的AnnotatedType实现的私有属性时,我仍然可以找到@Bar注释。 我正在运行最新版本的Java 8。

请看这个示例,你可以了解如何获取AnnotatedParameterizedType。但是,我不太确定如何从中获取注解。听起来你是在说你正在访问底层实现的私有字段。纯粹出于好奇,你能展示一下如何做到吗? - Paul Samsotha
我应该尝试那个。我立刻认为这是由于返回错误的类型表示引起的,但正如现在被接受的答案所述,这显然是一个错误。 - Rafael Winterhalter
3个回答

10

这是一个已知的错误JDK-8058220。然而,问题比看起来更加深入。

它不能轻易修复,需要对类文件格式进行更改及相应规范的更新。目前,类文件中不包含区分接收器参数和常规参数所需的信息(请参见JDK-8062582)。


这些都非常有趣,说明了合成/强制参数存在问题。然而,我不明白这与原始问题有何关联。通过示例代码,我可以完全访问接收器参数上的类型注释。问题 - 就我理解的方式而言 - 是我们应该如何访问放置在接收器参数类型的类型参数中的注释。foo(Foo<@Bar T> this) vs foo(@Bar Foo<T> this) - YoYo

1
原来这只是一个简单的错误。我最初认为这是链接问题的暗示,但类型注释与此无关。在当前Java运行时的实现中,类型注释测试不充分。当深入研究此问题时,我发现了大量问题:

-1
如果我运行这个代码:
Foo<Integer> f = new Foo<>();
Method m = f.getClass().getDeclaredMethod("foo");
AnnotatedType at = m.getAnnotatedReceiverType();
for (Annotation a:at.getAnnotations()) {
  System.out.println("Annotation: "+a);
}

然后我将注解放在接收器类型上,就像这样:

  public void foo(@Bar(1) Foo<T> this) {}

现在您可以访问@Bar(1)注释。请注意,我将注释直接放在ReceiverParameter上,而不是它的类型参数。

我知道现在这只是部分答案...但我想从某个地方开始。其他人可能会添加并提供完整的答案,或者随着时间的推移我会学到更多... Receiver Types和注释的使用对我来说都很新颖,没有太多的文档和示例可供参考。

我怀疑根本没有办法访问这些信息。另请参见另一个主题的答案

至于在方法参数中获取类型参数的注释的评论,根据上述内容,没有任何方法。

同一主题将向您展示如何访问字段中类型参数的注释。


我已经可以访问类型本身的注释,但不能访问带注释类型的参数。你提出的方法也适用于原始类型。Class实例从不表示泛型类型,您始终需要遍历其中一个才能调用getDeclaredMethod - Rafael Winterhalter
是的,我发现它适用于原始类型,并不得不修改我的答案,因为我最初声称它是问题的一部分,但实际上并不是。这真的很令人困惑和复杂,我怀疑我只是没有看到它应该如何使用。我认为这非常有趣,而且还没有得到真正的答案。 - YoYo

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