You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java子类方法重写:如何让Child1调用Child2的mymethod?

实现Child1调用Child2的mymethod的可行方案

先明确下你的核心需求:

让Child1的run()里调用的mymethod()指向Child2的实现,不能修改Father类的mymethod(),并且要保留Child2里的逻辑——满足if条件返回true,不满足就调用Father的原方法。

完全可以做到,下面给你两种最实用的方案:

方案一:直接修改Child1(最简单的路子)

既然需求只禁止修改Father的mymethod(),那我们直接在Child1里重写mymethod(),让它委托给Child2的实现就好。因为Child2的mymethod()是protected修饰的,只要Child1和Child2在同一个包下,或者通过实例调用(子类实例能访问父类的protected方法),就能直接调用。

修改后的Child1代码如下:

public class Child1 extends Father {
    public void run() {
        mymethod();
    }

    @Override
    protected boolean mymethod() {
        // 创建Child2实例,调用它的mymethod逻辑
        return new Child2().mymethod();
    }
}

这样一来,Child1的run()调用mymethod()时,就会直接执行Child2里的逻辑:满足条件返回true,不满足则调用Father的原方法,完美匹配你要的流程。

方案二:不修改Child1(用动态代理绕开)

如果因为某些原因不能改动Child1的代码,那我们可以用Java的动态代理技术,在运行时拦截Child1实例的mymethod()调用,把它转去执行Child2的版本。

情况1:如果类有实现接口(JDK动态代理)

如果Child1或者它的父类Father实现了某个接口,用JDK自带的动态代理就够了:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Child1ProxyHandler implements InvocationHandler {
    private final Father targetChild1;
    private final Child2 child2Delegate = new Child2();

    public Child1ProxyHandler(Father target) {
        this.targetChild1 = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 只拦截mymethod的调用
        if ("mymethod".equals(method.getName())) {
            return child2Delegate.mymethod();
        }
        // 其他方法还是用原Child1的逻辑
        return method.invoke(targetChild1, args);
    }

    // 生成代理实例的工具方法
    public static Father createProxy(Child1 original) {
        return (Father) Proxy.newProxyInstance(
                original.getClass().getClassLoader(),
                original.getClass().getInterfaces(),
                new Child1ProxyHandler(original)
        );
    }
}

使用的时候,不要直接用原Child1实例,改用代理后的实例:

public class Main {
    public static void main(String[] args) {
        Child1 original = new Child1();
        Father proxiedChild1 = Child1ProxyHandler.createProxy(original);
        proxiedChild1.run(); // 这里的run会触发Child2的mymethod
    }
}

情况2:没有实现接口(用CGLIB代理)

如果你的类没有实现任何接口,JDK动态代理就用不了,这时候可以用CGLIB来生成子类代理:

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;

public class Child1CglibProxy implements MethodInterceptor {
    private final Child1 originalChild1;
    private final Child2 child2Delegate = new Child2();

    public Child1CglibProxy(Child1 target) {
        this.originalChild1 = target;
    }

    public static Child1 createProxy(Child1 target) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Child1.class);
        enhancer.setCallback(new Child1CglibProxy(target));
        return (Child1) enhancer.create();
    }

    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        if ("mymethod".equals(method.getName())) {
            return child2Delegate.mymethod();
        }
        // 其他方法调用原类的逻辑
        return proxy.invokeSuper(obj, args);
    }
}

使用方式和JDK代理类似,替换成CGLIB生成的实例即可。

这两种方案都能完美实现你要的执行流程,选哪种就看你能不能修改Child1的代码啦~

内容的提问来源于stack exchange,提问作者MarEng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 04:06:28