问题
一位朋友提出了一个有趣的问题。给定以下代码:
public class OuterClass {
private String message = "Hello World";
private class InnerClass {
private String getMessage() {
return message;
}
}
}
从外部类,我如何打印message
变量内容?当然,不允许更改方法或字段的可访问性。
(这里的来源,但它是一个法国博客)
解决方案
解决这个问题的代码如下:
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
方法名称并不是真正标准的(即使这种格式是强烈推荐的格式),并且某些 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();
}
}
所以这个问题的有趣之处在于突出了合成方法的使用。使用这些方法,我可以像在解决方案中那样访问私有字段。当然,我需要使用反射,而且我认为使用这种东西可能会很危险......
问题
作为开发人员,对我来说,合成方法的兴趣是什么?什么是使用合成物有用的好情况?