基于泛型创建匿名类实例并覆写方法的技术问询
如何创建带方法覆写的T匿名实例
嘿,我懂你的需求——你想通过传入的Class<T extends Foo>对象,创建一个能覆写Foo中doStuff方法的匿名实例,但Class.newInstance()只能生成原类对象,没法直接加自定义逻辑。这里给你两种可行的解决方案,根据你的场景来选:
方案一:用JDK动态代理(适合Foo是接口的情况)
如果你能把Foo改成接口,那用JDK自带的动态代理就能轻松搞定,不用额外加依赖:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; // 先把Foo改成接口 public interface Foo { void doStuff(); } public class FooCreator { @SuppressWarnings("unchecked") public <T extends Foo> T getFoo(final Class<T> clazz) { return (T) Proxy.newProxyInstance( clazz.getClassLoader(), new Class<?>[]{clazz}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if ("doStuff".equals(method.getName())) { // 这里写你要覆写的自定义逻辑 System.out.println("我是覆写后的doStuff方法!"); return null; } // 其他方法调用原实现(如果有需要的话) return method.invoke(clazz.getDeclaredConstructor().newInstance(), args); } } ); } }
方案二:用CGLIB(支持普通类的子类生成)
如果Foo必须是类(就像你代码里写的那样),那JDK动态代理就不管用了,得用第三方库CGLIB来动态生成子类并覆写方法。
首先先添加CGLIB的Maven依赖:
<dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.3.0</version> </dependency>
然后实现你的getFoo方法:
import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class Foo { public void doStuff() { System.out.println("原Foo的doStuff执行"); } } public class FooCreator { @SuppressWarnings("unchecked") public <T extends Foo> T getFoo(final Class<T> clazz) { Enhancer enhancer = new Enhancer(); // 设置要继承的父类 enhancer.setSuperclass(clazz); // 设置方法拦截器,用来覆写指定方法 enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { if ("doStuff".equals(method.getName())) { // 自定义的覆写逻辑 System.out.println("这是覆写后的doStuff方法!"); return null; } // 其他方法调用父类的原实现 return proxy.invokeSuper(obj, args); } }); // 生成并返回子类实例 return (T) enhancer.create(); } }
几个要注意的点
- 如果你的
T是final类,那不管哪种方案都没法生成子类,这种情况就无解了,得确保T不是final的。 - 如果
T没有无参构造方法,那在CGLIB的enhancer.create()时要传入构造参数,比如enhancer.create(new Class[]{String.class}, new Object[]{"参数值"})。
内容的提问来源于stack exchange,提问作者Priv
相关产品推荐
相关产品推荐

