【发布时间】:2010-03-17 07:30:47
【问题描述】:
问题
一位朋友提出了一个有趣的问题。给定以下代码:
public class OuterClass {
private String message = "Hello World";
private class InnerClass {
private String getMessage() {
return message;
}
}
}
如何从外部类打印message 变量内容?当然,不允许更改方法或字段的可访问性。
(来源here,不过是法国博客)
解决方案
解决这个问题的代码如下:
try {
Method m = OuterClass.class.getDeclaredMethod("access$000", OuterClass.class);
OuterClass outerClass = new OuterClass();
System.out.println(m.invoke(outerClass, outerClass));
} catch (Exception e) {
e.printStackTrace();
}
注意access$000 方法名并不是真正的标准(即使这种格式是strongly recommanded),一些JVM 会将此方法命名为access$0。因此,更好的解决方案是检查合成方法:
Method method = null;
int i = 0;
while ((method == null) && (i < OuterClass.class.getDeclaredMethods().length)) {
if (OuterClass.class.getDeclaredMethods()[i].isSynthetic()) {
method = OuterClass.class.getDeclaredMethods()[i];
}
i++;
}
if (method != null) {
try {
System.out.println(method.invoke(null, new OuterClass()));
} catch (Exception e) {
e.printStackTrace();
}
}
所以这个问题的有趣之处在于突出了合成方法的使用。使用这些方法,我可以像在解决方案中那样访问私有字段。当然,我需要使用反射,而且我认为使用这种东西可能会很危险......
问题
对于作为开发人员的我来说,合成方法的兴趣是什么?什么情况下可以使用合成物?
【问题讨论】:
-
合成方法不是由 JVM 生成的。它们由 javac/scalac/fsc/groovyc/... 生成
标签: java reflection inner-classes java-synthetic-methods