Wednesday, July 16, 2008

Wednesday Afternoon Reflections

What does this print?

import java.lang.reflect.Method;

interface IMessage {
public CharSequence getMessage();
}

public class SayWhat implements IMessage {
public String getMessage() {
return "Hi!";
}

public static void main(String[] _args) {
try {
SayWhat instance = new SayWhat();
for (Method m : SayWhat.class.getMethods()) {
if (m.getName().equals("getMessage")) {
System.out.println("SayWhat.main: " + m.invoke(instance));
}
}
}
catch (Throwable e) {
System.out.println("SayWhat.main: " + e);
}
}
}

The answer is
Hi!
Hi!

That's right, the getMessage method appears twice in SayWhat.class.getMethods(). The key here is that the SayWhat class is overriding IMessage with a covariant return type (CharSequence vs. String). Looks like the compiler makes covariant return types possible by creating a behind-the-scenes "synthetic" implementation of getMessage which just calls through to my implementation.

If you find yourself looping through a list of Method objects looking for a match, be sure to check isSynthetic on each Method.

No comments: