This caught me offguard at first:
public class Scratch { public static class Qux { } public static class SubQuux extends Qux { } public static class Foo <M extends Qux> { public void spam(final M meat) { } } public static class Bar extends Foo<SubQuux> { public void spam(final SubQuux meat) { } } public static void main(final String[] args) { try { for (final Method method : Bar.class.getMethods()) if ("spam".equals(method.getName())) System.out.println(method); } catch (Exception e) { e.printStackTrace(); } } }
So, just what does main
print? The answer is fascinating:
public void Scratch$Bar.spam(Scratch$SubQuux) public volatile void Scratch$Bar.spam(Scratch$Qux)
Aha! Now I get it. Since the JDK5 compiler implements generics with type erasure, there needs to be a version of spam
which takes the lowest possibly erased type, Qux
, so that JDK1.4 runtimes can handle the method call. Crud. That messes up my reflection for messaging. However, the solution is staring right at me: volitile
. Since there really is no such method as public void Scratch$Bar.spam(Scratch$Qux)
, the compiler synthesizes one and marks it as volitile
. Nifty. Now I can filter those out with Modifier.isVolitile
. No harm, no foul.
No comments:
Post a Comment