18

I am looking at a rather trivial class with a single method that defines an annotated receiver type:

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

I would now like to access the type annotation on the receiver type's parameter @Bar but the Java reflection API returns an annotated raw type when accessing the receiver:

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

The assertion fails as the annotated type that is returned is returned as a raw type Foo. Is this intentional? I can still find the @Bar annotation when accessing private properties of the implementation of AnnotatedType that is returned.

I am running a recent version of Java 8.

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
  • You can see an example [here](https://gist.github.com/psamsotha/a68b9dafb457b3168ed7) on how to get the `AnnotatedParameterizedType`, but I am not quite sure from there how you would get the annotation. It sounds like you are saying that you are accessing the private fields of the underlying implementation. Just out of curiosity, could you show how you would do that? – Paul Samsotha Jan 06 '16 at 11:55
  • I should have tried that. I thought immediately this was caused by returning the wrong type representation but as stated by the now accepted answer, this apparently is a bug. – Rafael Winterhalter Jan 06 '16 at 12:18

3 Answers3

10

This is a known bug JDK-8058220. However, the problem is deeper that it may seem.

It cannot be easily fixed without changes to class file format and corresponding specification updates. Currently the class file does not contain information required to distinguish receiver parameter from a regular one (see JDK-8062582).

apangin
  • 92,924
  • 10
  • 193
  • 247
  • This is all very interesting, and shows there are issues with synthetic/mandated parameters. However I fail to see how that relates to the original question. With sample code I am perfectly able to access type annotations on a receiver parameter. The question - the way how I understand - is how we are supposed to access annotations put in the Type Parameters of the receiver parameter type. `foo(Foo<@Bar T> this)` vs `foo(@Bar Foo this)`. – YoYo Jan 06 '16 at 20:51
1

Turns out this is a simple bug. I first thought, this is an implicitation of the linked issues but type annotations have nothing to do with that. Type annotations are poorly tested in the current implementation of the Java runtime. I found a sheer number of issues when deep diving into the matter:

Rafael Winterhalter
  • 42,759
  • 13
  • 108
  • 192
-1

If I run this:

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);
}

Then I put the annotation on the Receiver Type like this:

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

Now you can access the @Bar(1) annotation. Note that I put the annotation directly on the ReceiverParameter, not it's Type Parameter as you want.

I know this is just a part answer right now ... but I wanted to start somewhere. Others might add and provide a complete answer, or I will learn a little more as time passes ... Receiver Types and such use of annotations is all very new to me, and no much documentation and samples to go by.

My suspicion is that there is just no way to accessing this information. See also the answer an another topic:

As for the comments, about getting the annotation from a type argument in a method parameter, there's no way given the above.

The same topic will show you how to access annotations on type arguments in a field.

Community
  • 1
  • 1
YoYo
  • 9,157
  • 8
  • 57
  • 74
  • I can already access an annotation on the type itself but not on a parameter of the annotated type. What you propose also works with a raw type. A `Class` instance never represents a generic type and you always need to walk through one of those in order to call `getDeclaredMethod`. – Rafael Winterhalter Jan 06 '16 at 09:07
  • Yes I discovered that it works on a raw type and had to modify my answer as I originally stated that as part of the problem, but it is not. It is really confusing and complex, I suspect that I just fail to see how it is supposed to be used. I think it is really interesting, and also not yet really answered. – YoYo Jan 06 '16 at 20:55