jdk8 lambda 是实现原理
- 定义一个函数式接口Func
@FunctionalInterface
interface Func extends Serializable {
String func(Object obj);
}
- 编写一段代码
Func func=Object::toString;
等价于,但上面最终可以获取toString方法名,下面只能获取到编译器生成的方法名
Func func=o->o.toString()
- 运行代码,jvm加上-Djdk.internal.lambda.dumpProxyClasses=(Path),可以看java.lang.invoke.InnerClassLambdaMetafactory类
public class MailMicroServiceApplication {
public static void main(String[] args) {
Func func=Object::toString;
func.func(new Object());
}
}
4.运行完成后会生成
5.idea 工具反编译后
package top.hunfan.mail;
import java.lang.invoke.SerializedLambda;
import java.lang.invoke.LambdaForm.Hidden;
// $FF: synthetic class
final class MailMicroServiceApplication$$Lambda$85 implements Func {
private MailMicroServiceApplication$$Lambda$85() {
}
@Hidden
public String func(Object var1) {
return var1.toString();
}
private final Object writeReplace() {
return new SerializedLambda(MailMicroServiceApplication.class, "top/hunfan/mail/Func", "func", "(Ljava/lang/Object;)Ljava/lang/String;", 5, "java/lang/Object", "toString", "()Ljava/lang/String;", "(Ljava/lang/Object;)Ljava/lang/String;", new Object[0]);
}
}
继承Serializable接口,lambda合成的类多出writeReplace方法,返回java.lang.invoke.SerializedLambda类,
该类的serializedLambda.getImplMethodName()方法可以返回方法名称
mybatis-plus的 LambdaQueryWrapper类实现
- LambdaQueryWrapper抽象类AbstractLambdaWrapper有一个方法
protected String columnToString(SFunction<T, ?> column, boolean onlyColumn) {
return getColumn(LambdaUtils.resolve(column), onlyColumn);
}
private String getColumn(SerializedLambda lambda, boolean onlyColumn) throws MybatisPlusException {
String fieldName = PropertyNamer.methodToProperty(lambda.getImplMethodName());
Class<?> aClass = lambda.getInstantiatedType();
if (!initColumnMap) {
columnMap = LambdaUtils.getColumnMap(aClass);
}
Assert.notNull(columnMap, "can not find lambda cache for this entity [%s]", aClass.getName());
ColumnCache columnCache = columnMap.get(LambdaUtils.formatKey(fieldName));
Assert.notNull(columnCache, "can not find lambda cache for this property [%s] of entity [%s]",
fieldName, aClass.getName());
return onlyColumn ? columnCache.getColumn() : columnCache.getColumnSelect();
}
原理也是借用jdk函数式接口实现Serializable接口后,序列化变成SerializedLambda类可以获取实现调用的方法
结论:
Func func=Object::toString;
Func函数接口有实现序列化接口,序列化后的SerializedLambda,调用getImplMethodName()方法可以得到“toString”