java - 如何保持 lambda 的参数类型?
问题描述
这是一个奇怪的 Java 反射问题,由于类型擦除而发生:
<P, R> void printIt(Function<P, R> function) {
inner(function);
}
private void inner(Object function) {
for (Method method : function.getClass().getDeclaredMethods()) {
System.out.println(method);
}
}
@Test
public void testAnyHandler() {
printIt((String a) -> "Hello");
}
结果是:
public java.lang.Object com.dariodario.sqlsmile.QueryTest$$Lambda$1/1607460018.apply(java.lang.Object)
真是太可惜了……有什么办法可以保留参数吗?
解决方案
并非如此,编译器不会保留此数据。您可以为 lambda 创建一个单独的类:
interface StringFunc extends Function<String, String> {}
然后就可以通过 StringFunc 超级接口来获取Function<String, String>
.
或者只使用类而不是 lambda:
printIt(new Function<String, String>() {
@Override
public String apply(String s) {
return s;
}
});
Lambda 还在声明它们的类中生成合成方法:
Function<String, String> x = (String a) -> a;
printIt(x);
for (Method declaredMethod : Test.class.getDeclaredMethods()) {
if (declaredMethod.isSynthetic()) {
System.out.println(declaredMethod);
}
}
}
将打印
public java.lang.Object org.gotofinal.Test$$Lambda$14/0x0000000800066840.apply(java.lang.Object)
private static java.lang.String org.gotofinal.Test.lambda$main$0(java.lang.String)
但是我看不到获取 lambda 声明类的选项(但可以从类名中提取)以及如何将方法与 lambda 匹配 + 它是特定于实现的,因此可能不适用于每个 jvm 版本。此方法还将包括传递给 lambda 的局部变量类型:
int dd = "dddd".length() + args.length;
Function<String, String> x = (String a) -> a + dd;
将打印:
private static java.lang.String org.gotofinal.Test.lambda$main$0(int,java.lang.String)
所以可能你最好的选择是将类型作为单独的参数传递:
public <F, T> Whatever method(Class<F> typeF, Class<T> typeT, Function<F, T> func)
推荐阅读
- sql-server - 如何解决灯泡服务器中的重定向问题?
- visual-studio-code - 在 mac 上使用终端命令打开 vscode 时似乎找不到 bash_profile
- java - 如何通过单击按钮更改标签文本?
- electron - 'v8::ArrayBuffer' 中的'GetContents'
- json - JupyterLab 工作区是否在重新启动之间持续存在?
- reactjs - 你如何为注入的 HOC 编写 typescript 类型
- sql-server - 我可以使用 .sql 查询文件作为 SSIS 中的数据源吗
- reporting-services - SSRS - 重新处理丢失的电子邮件订阅
- python - Python创建函数在调用它的函数中自动创建变量?
- javascript - 无法从 localhost 访问 Express.js 路由