如何通过Class<?>对象调用Java接口的默认方法?
调用接口默认方法的两种实现方案
针对你提出的通过Class对象调用接口默认方法的需求,这里提供两种无需修改接口定义的实现方式:
方案一:动态代理生成接口实例
通过JDK动态代理创建接口的代理对象,自动实现所有抽象方法(返回默认值或空操作),再用该实例调用默认方法:
import java.lang.invoke.MethodHandles; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class DefaultMethodInvoker { @SuppressWarnings("unchecked") public static <T> String getReturnValueOfInterfaceMethod(Class<T> clazz, String method_name) throws Exception { if (!clazz.isInterface()) return null; Method m = clazz.getMethod(method_name); if (!m.isDefault()) throw new Exception("目标方法不是默认方法"); // 创建接口的动态代理实例 T proxyInstance = (T) Proxy.newProxyInstance( clazz.getClassLoader(), new Class[]{clazz}, (proxy, method, args) -> { if (method.isDefault()) { // 调用默认方法 return MethodHandles.lookup() .in(clazz) .unreflectSpecial(method, clazz) .bindTo(proxy) .invokeWithArguments(args); } else { // 为抽象方法提供默认实现 Class<?> returnType = method.getReturnType(); if (returnType == void.class) return null; if (returnType.isPrimitive()) { switch (returnType.getName()) { case "int": return 0; case "boolean": return false; case "long": return 0L; case "float": return 0.0f; case "double": return 0.0d; case "short": return (short) 0; case "byte": return (byte) 0; case "char": return '\u0000'; } } return null; } } ); return (String) m.invoke(proxyInstance); } }
方案二:通过MethodHandle直接调用默认方法
利用Java 8引入的MethodHandlesAPI,无需创建完整的接口实例,直接获取默认方法的句柄并调用:
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Method; public class DefaultMethodInvoker { public static <T> String getReturnValueOfInterfaceMethod(Class<T> clazz, String method_name) throws Exception { if (!clazz.isInterface()) return null; Method method = clazz.getMethod(method_name); if (!method.isDefault()) throw new Exception("目标方法不是默认方法"); // 获取默认方法的方法句柄 MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle methodHandle = lookup.findSpecial( clazz, method_name, MethodType.methodType(method.getReturnType()), clazz ); // 调用默认方法,传入null作为this参数(接口默认方法允许此操作) return (String) methodHandle.invokeExact(null); } }
两种方案对比
- 动态代理方案:通用性强,适配任意包含抽象方法的接口,适合需要复用接口实例的场景,但首次创建代理类存在轻微性能开销。
- MethodHandle方案:更轻量高效,无需生成代理类,适合单次调用默认方法的场景,但要求严格匹配方法签名(
invokeExact对参数和返回类型的匹配度要求极高)。
内容的提问来源于stack exchange,提问作者Sus Amongus
相关产品推荐
相关产品推荐

