方法引用获取字段名称
引言:
此段需要lambda和函数时接口知识,不了解的可以去补充下哦
在使用Mybatis-Plus的LambdaQueryWrapper时,经常会看到下面这段代码:
wrapper.ge(User::getInfo,"xxx");
我们都知道ge()方法第一个参数是字段名称,那么在java中是如何通过方法引用获取到字段名称的呢?
SerializedLambda类
Java8 lambda函数接口如果继承了Serializable这个接口,那么把lambda函数的实例对象序列化成字节,然后再使用ObjectInputStream反序列化成一个对象,此时反序列化获得的对象是SerializedLambda类型的一个实例。
关键类在于SerializedLambda,此类实现了Serializable接口
// 源码
public final class SerializedLambda implements Serializable
比如 User::getInfo 这个 lambda 表达式,底层接收的函数接口是继承了 Serializable接口的话,比如Mybatis-plus的SFunction函数接口。
每次传入User::getInfo这个方法引用作为参数给SFunction接口时,底层都是创建一个SFunction的实例对象,这个对象封装了对User的getInfo方法的调用。
测试
创建自定义函数式接口
@FunctionalInterface
public interface IGetter<T,R> extends Serializable {
R get(T source);
}
创建Java Bean
public class User {
private Long id;
private String info;
private String query;
// ...getter setter省略
}
测试
public class Test {
public static void main(String[] args) {
IGetter<User, String> fn = User::getQuery;
try {
Method method = fn.getClass().getDeclaredMethod("writeReplace");
method.setAccessible(true);
SerializedLambda lambda = (SerializedLambda) method.invoke(fn);
System.out.println("lambda.getImplClass() = " + lambda.getImplClass());
System.out.println("lambda.getImplMethodName() = " + lambda.getImplMethodName());
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
}
}
输出
得到方法名称之后,只需提取字段名称即可