java - 合成方法有什么好处?

标签 java reflection inner-classes java-synthetic-methods

问题

一位 friend 提出了一个有趣的问题。给定以下代码:

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();
    }
}

所以这个问题的有趣点在于突出合成方法的使用。使用这些方法,我可以像在解决方案中那样访问私有(private)字段。当然,我需要用到反射,而且我认为使用这种东西是相当危险的......

问题

作为开发人员,我对合成方法有什么兴趣?什么是使用合成有用的好情况?

最佳答案

正如您所演示的,Java 访问修饰符只是提供信息,可以通过使用反射来规避它们。所以你的问题大致等同于“规避访问修饰符的好处是什么?”除了恶意目的,还想到了调试;例如,您可以从库的外部记录某些库内部的内部状态,而根本不必触及库代码本身。另一个例子是与脚本语言的合作;如果您在编译时不知道哪些类和方法可用,反射可能非常有用。例如,Jython的内部使用了大量的反射。

关于java - 合成方法有什么好处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2460502/

相关文章:

java - 有没有办法通过知道相对于java中文本节点的索引来查找xml中的特定位置?

java - 使用反射调用方法时 int 和 Integer 参数的区别

java - 为什么编译器无法推断 Java 中内部类的泛型类型?

c# - 从 IL 构造方法引用集合

java - 使用 null 参数调用 Class.newInstance 会导致 IllegalArgumentException

java - groovy中的匿名内部类

java - 如何通过反射获取内部类中存在的枚举的值

java - android gomobile 上的 "Unsupported flags DT_FLAGS_1=0x9"错误

java - 功能接口(interface)和方法引用的行为

java - List.toArray(T[]) 的奇怪泛型行为