3 回答

TA贡献1946条经验 获得超3个赞
如何将lambda代码映射到接口实现的确切决定留给实际的运行时环境。原则上,实现相同原始接口的所有lambda都可以共享一个运行时类,就像这样MethodHandleProxies做一样。对特定的lambda使用不同的类是由实际实现执行的优化,LambdaMetafactory但不是旨在帮助调试或反射的功能。
因此,即使您在lambda接口实现的实际运行时类中找到了更详细的信息,它也将是当前使用的运行时环境的产物,在不同的实现甚至您当前环境的其他版本中可能不可用。
如果是lambda,则Serializable可以使用序列化的表单包含实例化接口类型的方法签名这一事实来一起混淆实际的类型变量值。

TA贡献1893条经验 获得超10个赞
参数化类型信息仅在运行时可用于绑定的代码元素-即专门编译成类型的代码元素。Lambda执行相同的操作,但是由于Lambda不支持方法而不是类型,因此没有类型可以捕获该信息。
考虑以下:
import java.util.Arrays;
import java.util.function.Function;
public class Erasure {
static class RetainedFunction implements Function<Integer,String> {
public String apply(Integer t) {
return String.valueOf(t);
}
}
public static void main(String[] args) throws Exception {
Function<Integer,String> f0 = new RetainedFunction();
Function<Integer,String> f1 = new Function<Integer,String>() {
public String apply(Integer t) {
return String.valueOf(t);
}
};
Function<Integer,String> f2 = String::valueOf;
Function<Integer,String> f3 = i -> String.valueOf(i);
for (Function<Integer,String> f : Arrays.asList(f0, f1, f2, f3)) {
try {
System.out.println(f.getClass().getMethod("apply", Integer.class).toString());
} catch (NoSuchMethodException e) {
System.out.println(f.getClass().getMethod("apply", Object.class).toString());
}
System.out.println(Arrays.toString(f.getClass().getGenericInterfaces()));
}
}
}
f0并f1按照您的期望保留了它们的通用类型信息。但是由于它们是未绑定的方法,因此已被擦除为Function<Object,Object>,f2而f3不是。
添加回答
举报