Java's compiler not retaining generic method annotations? -


i encountering issue java's generic type erasure , runtime annotations , not sure whether doing wrong or bug in java compiler. consider following minimal working example:

@target({ elementtype.method, elementtype.type }) @retention(retentionpolicy.runtime) @inherited public @interface myannotation { }  public interface mygenericinterface<t> {     void hello(t there); }  public class myobject { }  public class myclass implements mygenericinterface<myobject> {     @override     @myannotation     public void hello(final myobject there) {     } } 

now when query information myclass.hello reflection expect hello method still has annotation, not:

public class mytest {      @test     public void testname() throws exception {         method[] declaredmethods = myclass.class.getdeclaredmethods();         (method method : declaredmethods) {             assert.assertnotnull(string.format("method '%s' not annotated.", method), method                     .getannotation(myannotation.class));         }     }  } 

the (unexpected) error message reads follows:

java.lang.assertionerror: method 'public void test.myclass.hello(java.lang.object)' not annotated.

tested java 1.7.60.

as has been pointed out others, compilation generates 2 methods same name, hello(object) , hello(myobject).

the reason type erasure:

mygenericinterface mgi = new myclass(); c.hello( "hahaha" ); 

the above should compile because erasure of void hello(t) void hello(object). of course should fail @ runtime because there no implementation accept arbitrary object.

from above can conclude void hello(myobject) not in fact valid override method. generics useless if couldn't "override" method type parameter.

the way compiler gets around generate synthetic method signature void hello(object), checks input parameter type @ runtime , delegates void hello(myobject), if check successful. can see in byte code in john farrelly's answer.

so class looks (observe how annotation stays on original method):

public class myclass implements mygenericinterface<myobject> {      @myannotation      public void hello(final myobject there) {      }       @override      public void hello(object ob) {          hello((myobject)ob);      } } 

luckily, because it's synthetic method, can filter out void hello(object) checking value of method.issynthetic(), if it's true should ignore purposes of annotation processing.

@test public void testname() throws exception {     method[] declaredmethods = myclass.class.getdeclaredmethods();     (method method : declaredmethods) {         if (!method.issynthetic()) {              assert.assertnotnull(string.format("method '%s' not annotated.", method), method                 .getannotation(myannotation.class));         }     } } 

this should work fine.

update: according this rfe, annotations should copied across bridge methods well.


Comments

Popular posts from this blog

python - No exponential form of the z-axis in matplotlib-3D-plots -

php - Best Light server (Linux + Web server + Database) for Raspberry Pi -

c# - "Newtonsoft.Json.JsonSerializationException unable to find constructor to use for types" error when deserializing class -