【问题标题】:Java reflection: How do I override or generate methods at runtime?Java 反射:如何在运行时覆盖或生成方法?
【发布时间】:2026-01-01 16:40:01
【问题描述】:

在纯 Java 中可以覆盖类的方法 在运行时以编程方式(甚至创建新方法)?

即使我在编译时知道类,我也希望能够做到这一点。

我在运行时覆盖的确切意思:

abstract class MyClass{
  public void myMethod();
}

class Overrider extends MyClass{
  @Override
  public void myMethod(){}
}

class Injector{
  public static void myMethod(){ // STATIC !!!
    // do actual stuff
  }
}

// some magic code goes here
Overrider altered = doMagic(
    MyClass.class, Overrider.class, Injector.class);

现在,这个调用...

altered.myMethod();

...将调用 Injector.myMethod() 而不是 Overrider.myMethod()

Injector.myMethod() 是 static,因为,在做了“魔术”之后 它是从不同的类实例调用的(它是 Overrider), (所以我们阻止它访问本地字段)。

【问题讨论】:

  • 你能告诉我们你想要覆盖什么样的对象吗?乍一看,您的问题让我想起了依赖注入范式的目标。

标签: java reflection code-generation runtime


【解决方案1】:

您可以使用 cglib 之类的东西即时生成代码

【讨论】:

    【解决方案2】:

    在 java6 中添加了转换任何已加载类的可能性。看看java.lang.instrument包里的changes

    【讨论】:

    • 我什至忘记了这个包的存在!谢谢!
    【解决方案3】:

    对于接口有java.lang.reflect.Proxy

    对于类,您要么需要第三方库,要么编写大量代码。一般用这种方式动态创建类就是为了创建mock进行测试。

    还有允许修改类的检测 API。您还可以使用自定义类加载器或仅修改磁盘上的类文件来修改类。

    【讨论】:

    • @T.H.t:在您看来,AOP 或 BCEL 风格的重新设计是否也适用于这种情况?我目前面临类似的问题,无法决定使用什么。
    • AOP 非常通用。我更喜欢 ASM 而不是 BCEL。 oxbow_lakes 提到了 cglib,我不记得它的名字(也没有使用过)。
    【解决方案4】:

    我写了一篇article for java.net,关于如何在类加载器使用 java 代理加载类时透明地添加日志记录语句。

    它使用 Javassist 库来操作字节码,包括使用 Javassist 编译器生成额外的字节码,然后将其插入适当的位置,然后将生成的类提供给类加载器。

    slf4j 项目提供精炼版本。

    【讨论】:

    • 现在几年后,我不会推荐这种方法。如果您真的需要这个,请查看面向方面的编程。
    【解决方案5】:

    如果我没记错的话,您关心的主要问题是如何通过实例接口方法传递静态方法委托(如在 C# 中)。

    您可以查看这篇文章:A Java Programmer Looks at C# Delegates (archived),它向您展示了如何获取对静态方法的引用并调用它。然后,您可以创建一个包装类,该类在其构造函数中接受静态方法名称,并实现您的基类以从实例方法调用静态方法。

    【讨论】:

    • 链接已损坏。
    最近更新 更多