Java中静态数组内存储实例方法引用时func成员的类型如何声明
问题解答
这个需求完全可以实现,核心是要匹配未绑定的非静态实例方法引用的函数式接口签名。
原理说明
你用到的MyClass::f1属于「未绑定的非静态方法引用」,没有和具体的MyClass实例绑定,调用时需要显式传入实例作为第一个参数,再传入方法本身的入参。方法f1的原始签名为:
(MyClass实例, int 参数) -> int 返回值
只要函数式接口的抽象方法匹配这个签名,就能接收这个方法引用。
方案1:自定义函数式接口(推荐,无拆箱开销)
首先定义匹配签名的函数式接口:
@FunctionalInterface public interface MyClassMethod { // 第一个参数为方法所属的实例,第二个参数为方法的入参 int invoke(MyClass instance, int arg); }
再定义你的规则类(注意不要用Record作为自定义类名,会和JDK内置的java.lang.Record冲突,建议改名RegexRule):
// JDK 16+ 记录类写法 public record RegexRule(Pattern regex, MyClassMethod func) {} // 低版本JDK普通类写法 public class RegexRule { private final Pattern regex; private final MyClassMethod func; public RegexRule(Pattern regex, MyClassMethod func) { this.regex = regex; this.func = func; } // 按需添加getter方法 }
你的静态数组定义不需要修改,直接兼容:
static final RegexRule[] table = { new RegexRule( Pattern.compile( "regex1" ), MyClass::f1 ), new RegexRule( Pattern.compile( "regex2" ), MyClass::f2 ) };
调用逻辑和你的伪代码完全一致,修改方法名即可:
void foo( String s, int arg ) { for( RegexRule r : table ) { if( r.regex().matcher( s ).matches() ) { int result = r.func().invoke( this, arg ); break; } } }
方案2:使用JDK内置函数式接口(无需自定义,有拆箱开销)
如果不想单独定义函数式接口,可以用JDK自带的BiFunction,接收两个参数返回一个结果,缺点是会涉及基本类型和包装类的拆箱装箱:
// 规则类定义,func类型为BiFunction<实例类型, 入参类型, 返回值类型> public record RegexRule(Pattern regex, BiFunction<MyClass, Integer, Integer> func) {}
调用时使用apply方法:
int result = r.func().apply(this, arg);
静态方法和非静态方法的适配差异
静态方法不需要依赖实例,方法引用的签名为(int) -> int,只需要一个入参,用Function<Integer, Integer>就能接收。非静态方法多了一个隐式的实例参数,你之前用静态方法的签名来适配非静态方法才会报错。
内容的提问来源于stack exchange,提问作者Johannes Ernst
相关产品推荐
相关产品推荐

