最近在使用mybatis-plus框架,咱们都知道有这么一种写法,能够经过lambda的方法引用得到属性值,避免魔法值的大量出现java
public List<Board> getListByName() {
LambdaQueryWrapper<Board> wrapper = new LambdaQueryWrapper<>();
// lambda方法引用
queryWrapper.eq(User::getName, "小明");
return xxxserver.list(wrapper);
}
复制代码
对于mybatis-plus的这类实现已经有博主写了,不了解的能够参考blog.csdn.net/u012503481/…这篇文章缓存
那么咱们确定在不少开发场景须要用到Java Bean的属性名,直接写死属性名字符串的形式容易产生bug(属性名一旦变化,IDE不会告诉你你的字符串须要同步修改)。JDK8的Lambda能够经过方法引用简化代码,一样也能够经过getter/setter的方法引用拿到属性名,避免潜在的bug。mybatis
// 传统方式:写死属性名
// 方法引用:替代字符串,当属性名变化时IDE会同步提示,避免未同步产生bug
String userName = BeanUtils.convertToFieldName(User::getUserName);复制代码
首先咱们定义1个函数式接口用来接收lambda方法引用表达式:注意函数式接口必定要继承Serializable接口才能获取方法信息。app
package com.changda.singleton;
import java.io.Serializable;
/** * @classname: SFunction * @create: 2019-09-25 12:57 **/
@FunctionalInterface
public interface SFunction<T> extends Serializable {
Object get(T source);
}
复制代码
其次咱们实现一个getter引用转换属性名的工具类【注释基本都写好啦,稍有不懂的话,自行百度一下】框架
package com.changda.singleton;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/** * @classname: BeanUtils * @create: 2019-09-25 18:13 **/
class BeanUtils {
private static Map<Class, SerializedLambda> CLASS_LAMDBA_CACHE = new ConcurrentHashMap<>();
/*** * 转换方法引用为属性名 * @param fn * @return */
static <T> String convertToFieldName(SFunction<T> fn) {
SerializedLambda lambda = getSerializedLambda(fn);
// 获取方法名
String methodName = lambda.getImplMethodName();
String prefix = null;
if(methodName.startsWith("get")){
prefix = "get";
}
else if(methodName.startsWith("is")){
prefix = "is";
}
if(prefix == null){
System.out.println("无效的getter方法: "+ methodName);
}
// 截取get/is以后的字符串并转换首字母为小写
return toLowerCaseFirstOne(methodName.replace(prefix, ""));
}
/** * 首字母转小写 * @param s * @return */
static String toLowerCaseFirstOne(String s){
if(Character.isLowerCase(s.charAt(0)))
return s;
else
return Character.toLowerCase(s.charAt(0)) + s.substring(1);
}
/** * 关键在于这个方法 */
static SerializedLambda getSerializedLambda(Serializable fn) {
SerializedLambda lambda = CLASS_LAMDBA_CACHE.get(fn.getClass());
// 先检查缓存中是否已存在
if(lambda == null) {
try {
// 提取SerializedLambda并缓存
Method method = fn.getClass().getDeclaredMethod("writeReplace");
method.setAccessible(Boolean.TRUE);
lambda = (SerializedLambda) method.invoke(fn);
CLASS_LAMDBA_CACHE.put(fn.getClass(), lambda);
} catch (Exception e) {
e.printStackTrace();
}
}
return lambda;
}
}
复制代码
先简单建立一个实体类函数
package com.changda.singleton;
/** * @create: 2019-09-25 13:17 **/
public class Test {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
复制代码
而后调用试试工具
package com.changda.singleton;
/** * @create: 2019-09-25 13:16 **/
public class Demo {
public static void main(String[] args) {
System.out.println(BeanUtils.convertToFieldName(Test::getName));
}
}
复制代码
结果以下:测试
这样就大功告成了,能够使用方法引用了,不再用担忧打错字符咯。this