LambdaConversionException排查:LambdaMetafactory调用实例方法参数错误
问题排查与解决
错误原因分析
抛出java.lang.invoke.LambdaConversionException: Incorrect number of parameters for instance method invokeVirtual的核心原因是Lambda元工厂的方法类型参数不匹配:
- 你试图生成
Supplier<String>类型的Lambda,但Supplier的单一抽象方法(SAM)是get(),无参数且返回String。 - 你的配置中,
samMethodType指定为MethodType.methodType(String.class, Person.class)(需要一个Person参数),但Supplier的方法签名并不接受参数,导致参数数量不匹配。
两种修复方案
方案1:改用Function<Person, String>(更直接)
如果希望Lambda接收Person实例并返回name,使用Function接口更合适,它的SAM方法apply(T)刚好匹配"接收Person,返回String"的签名:
package edu.project5; import java.lang.invoke.*; import java.util.function.Function; import static java.lang.invoke.MethodType.methodType; public class LambdaExample { public static void main(String[] args) throws Throwable { record Person(String name, int age) {} MethodHandles.Lookup lookup = MethodHandles.lookup(); // 获取Person的name()方法句柄,实例方法默认第一个参数是this(Person类型) MethodHandle methodHandle = lookup.findVirtual(Person.class, "name", methodType(String.class)); CallSite callSite = LambdaMetafactory.metafactory( lookup, "apply", // Function的SAM方法名 MethodType.methodType(Function.class), // 工厂方法返回Function,无额外参数 methodType(String.class, Person.class), // SAM方法的签名:(Person) -> String methodHandle, // 目标方法句柄 methodType(String.class, Person.class) // 目标方法的实际签名(和SAM一致) ); MethodHandle factory = callSite.getTarget(); Function<Person, String> nameExtractor = (Function<Person, String>) factory.invokeExact(); Person person = new Person("John", 30); System.out.println("Extracted Name: " + nameExtractor.apply(person)); } }
方案2:绑定Person实例到方法句柄,生成Supplier
如果一定要生成Supplier<String>,需要提前把Person实例绑定到方法句柄上,让方法句柄变成无参调用:
package edu.project5; import java.lang.invoke.*; import java.util.function.Supplier; import static java.lang.invoke.MethodType.methodType; public class LambdaExample { public static void main(String[] args) throws Throwable { record Person(String name, int age) {} Person person = new Person("John", 30); MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle methodHandle = lookup.findVirtual(Person.class, "name", methodType(String.class)); // 绑定person实例到方法句柄的第一个参数(this),生成无参的方法句柄 MethodHandle boundHandle = methodHandle.bindTo(person); CallSite callSite = LambdaMetafactory.metafactory( lookup, "get", // Supplier的SAM方法名 MethodType.methodType(Supplier.class), // 工厂方法返回Supplier,无额外参数 methodType(String.class), // SAM方法的签名:() -> String boundHandle, // 已绑定实例的方法句柄 methodType(String.class) // 目标方法的实际签名(无参返回String) ); MethodHandle factory = callSite.getTarget(); Supplier<String> nameExtractor = (Supplier<String>) factory.invokeExact(); System.out.println("Extracted Name: " + nameExtractor.get()); } }
LambdaMetafactory核心参数说明
避免再踩坑,明确几个关键参数的作用:
invokedName:要实现的SAM接口的方法名(比如Supplier的get,Function的apply)invokedType:工厂方法的类型,即调用Lambda工厂时的参数和返回值类型samMethodType:SAM接口方法的签名(参数类型+返回值类型)implMethod:实际要调用的方法句柄instantiatedMethodType:实际方法的签名,必须和samMethodType兼容
内容的提问来源于stack exchange,提问作者Black Winst
相关产品推荐
相关产品推荐

