2016-01-01 54 views
16

我在看一个相当琐碎类定义了一个注解接收器类型一个方法:如何访问类型注解接收器类型的参数

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

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

assert Foo.class.getDeclaredMethod("foo") 
       .getAnnotatedReceiverType() 
    instanceof AnnotatedParameterizedType; 

断言失败为返回的注释类型是returne d作为原始类型Foo。这是故意的吗?在访问返回的AnnotatedType的实现的私有属性时,我仍然可以找到@Bar注释。

我运行最新的Java 8

+0

你可以看到一个例子[这里](HTTPS:/ /gist.github.com/psamsotha/a68b9dafb457b3168ed7)关于如何获得'AnnotatedParameterizedType',但我不太确定从那里你将如何得到注释。这听起来像你在说你正在访问底层实现的私有领域。出于好奇,你能证明你会怎么做? –

+0

我应该尝试过。我立刻想到这是由于返回错误的类型表示造成的,但正如现在接受的答案所述,这显然是一个错误。 –

回答

0

原来这是一个简单的错误。我首先想到的是,这是对相关问题的暗示,但类型注释与此无关。类型注释在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和注解的这种使用对我而言都是非常新的,没有太多的文档和样本可供借鉴。

我怀疑是没有办法访问这些信息。也the answer an another topic参见:

对于注释,约从方法参数类型参数得到注解,也没有给出上述方式。

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

+0

我已经可以访问类型本身的注释,但不能注释注释类型的参数。你提出的建议也适用于原始类型。一个'Class'实例永远不会代表一个泛型类型,你总是需要通过其中一个来调用'getDeclaredMethod'。 –

+0

是的,我发现它在原始类型上工作,并且必须修改我的答案,因为我原来说这是问题的一部分,但事实并非如此。这真是令人困惑和复杂,我怀疑我只是没有看到它应该如何使用。我认为这非常有趣,也没有真正回答。 – YoYo

7

这是一个已知的bug JDK-8058220。但是,问题看起来可能更深。

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

+0

这是非常有趣的,并显示有合成/强制参数的问题。但是我没有看到这与原来的问题有什么关系。通过示例代码,我完全能够访问接收器参数上的类型注释。这个问题 - 我理解的方式 - 就是我们应该如何访问放入接收器参数类型的类型参数中的注释。 'foo(Foo <@Bar T> this)'vs'foo(@Boo Foo this)'。 – YoYo