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

如何创建代理并调用默认接口方法,使其复用父类实现?

实现Bar接口代理并复用Super类方法逻辑的方案

要实现这个需求,核心是利用Java动态代理的InvocationHandler来拦截方法调用,让默认方法内部的returnSomething()调用转发到Super类的实现上。下面是具体的实现步骤和代码示例:

核心思路

  1. 创建动态代理实现Bar接口,代理的InvocationHandler持有Super类的实例,用于复用其returnSomething()逻辑。
  2. 当调用Bar的默认方法returnSomethingMore()时,通过MethodHandles触发默认方法的执行;此时默认方法内部的returnSomething()调用会被代理拦截,转而调用Super实例的对应方法。
  3. 对Foo接口的returnSomething()方法做特殊处理,直接转发到Super实例的实现。

完整代码示例

import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

// 原定义的接口和类
interface Foo {
    default int returnSomething() { return 1; }
}

interface Bar extends Foo {
    default int returnSomethingMore() { return returnSomething(); }
}

class Super implements Foo {
    @Override
    public int returnSomething() { return 2; }
}

public class BarProxyDemo {
    public static void main(String[] args) {
        // 创建Super实例,复用它的returnSomething逻辑
        Super superLogic = new Super();
        
        // 生成Bar接口的代理对象
        Bar barProxy = (Bar) Proxy.newProxyInstance(
                Bar.class.getClassLoader(),
                new Class<?>[]{Bar.class},
                new BarProxyHandler(superLogic)
        );
        
        // 调用默认方法,预期输出2(复用Super的returnSomething)
        System.out.println(barProxy.returnSomethingMore());
    }

    // 自定义InvocationHandler处理代理方法调用
    static class BarProxyHandler implements InvocationHandler {
        private final Super superInstance;

        public BarProxyHandler(Super superInstance) {
            this.superInstance = superInstance;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 处理默认方法:调用接口的默认实现逻辑
            if (method.isDefault()) {
                return invokeDefaultInterfaceMethod(proxy, method, args);
            }
            
            // 处理Foo接口的returnSomething方法,转发到Super实例
            if (method.getDeclaringClass() == Foo.class && method.getName().equals("returnSomething")) {
                return superInstance.returnSomething();
            }
            
            // 其他未处理的方法抛出异常
            throw new UnsupportedOperationException("Unsupported method: " + method.getName());
        }

        // 调用接口默认方法的工具方法
        private Object invokeDefaultInterfaceMethod(Object proxy, Method method, Object[] args) throws Throwable {
            MethodHandles.Lookup lookup = MethodHandles.lookup();
            return lookup.findSpecial(
                    method.getDeclaringClass(),
                    method.getName(),
                    MethodType.methodType(method.getReturnType(), method.getParameterTypes()),
                    method.getDeclaringClass()
            ).bindTo(proxy).invokeWithArguments(args);
        }
    }
}

关键细节说明

  • 默认方法调用:Java反射无法直接调用接口默认方法,所以我们用MethodHandles.Lookup来获取并执行默认方法的逻辑,绑定的this是代理对象,这样默认方法内部的后续调用会被代理拦截。
  • 方法转发逻辑:当默认方法内部调用returnSomething()时,这个调用会进入InvocationHandler的invoke方法,我们在这里把它转发给Super实例的实现,从而复用了Super的业务逻辑。
  • 类型判断:通过method.isDefault()区分默认方法和普通接口方法,确保不同类型的方法得到正确处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:22:26