Java如何基于泛型实例和泛型函数实现对象方法调用?
问题描述
我想编写如下这样的方法:
<T> void callFuncOnObj(T obj, Runnable r) { obj.r(); //or r.runOnTheInstance(obj); }
并能像这样调用(忽略异常):
callFuncOnObj(System.in, InputStream::close);
显然,Runnable并不支持这种用法。InputStream::close的类型似乎只是Object,那么该如何使用或转换它,才能让泛型实例调用它呢?
我能想到的最直接替代方案是接收Method对象,并在不适用时处理IllegalArgumentException:
void callFuncOnObj(Object obj, Method m) { try{ m.invoke(obj); }catch(IllegalArgumentException iae) { ... }... }
有没有一种基于泛型实例和泛型函数的更好实现方式?
解决方案
当然有,Java内置的函数式接口就能完美解决这个问题,不需要依赖反射的Method.invoke。你可以使用**Consumer<T>**这个函数式接口,它的设计就是接收一个参数并执行对应的操作,完全匹配实例方法引用的场景。
修改后的泛型方法
<T> void callFuncOnObj(T obj, Consumer<T> action) { action.accept(obj); }
调用方式
这样就能按照你想要的方式调用了:
callFuncOnObj(System.in, InputStream::close);
原理说明
InputStream::close作为实例方法引用,它的实际类型是Consumer<InputStream>,当泛型T被编译器自动推断为InputStream时,方法参数类型完全匹配。Consumer的accept(T t)方法会接收传入的obj实例,并调用对应的实例方法,全程是类型安全的——编译期就能检查出方法引用是否匹配目标类型,比反射更高效,也避免了反射带来的异常处理麻烦。
异常处理扩展
如果需要处理方法可能抛出的异常,可以自定义一个支持抛出异常的函数式接口:
@FunctionalInterface interface ThrowingConsumer<T, E extends Exception> { void accept(T t) throws E; }
然后修改方法来传递异常:
<T, E extends Exception> void callFuncOnObj(T obj, ThrowingConsumer<T, E> action) throws E { action.accept(obj); }
调用时就可以直接捕获或抛出异常:
try { callFuncOnObj(System.in, InputStream::close); } catch (IOException e) { // 处理IO异常 }
内容的提问来源于stack exchange,提问作者user21583770
相关产品推荐
相关产品推荐

