通过Lambda的get方法引用拿到私有属性名

导读:本篇文章讲解 通过Lambda的get方法引用拿到私有属性名,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

前言:

最近在使用mybatis-plus框架,我们都知道有这么一种写法,可以通过lambda的方法引用获得属性值,避免魔法值的大量出现

通过Lambda的get方法引用拿到私有属性名

public List<Board> getListByName() {
  LambdaQueryWrapper<Board> wrapper = new LambdaQueryWrapper<>();
  // lambda方法引用
  queryWrapper.eq(User::getName, "小明");
  return xxxserver.list(wrapper);
}

对于mybatis-plus的这类实现已经有博主写了,不了解的可以参考https://blog.csdn.net/u012503481/article/details/100896507这篇文章

那么我们肯定在很多开发场景需要用到Java Bean的属性名,直接写死属性名字符串的形式容易产生bug(属性名一旦变化,IDE不会告诉你你的字符串需要同步修改)。JDK8的Lambda可以通过方法引用简化代码,同样也可以通过getter/setter的方法引用拿到属性名,避免潜在的bug。

期望实现效果:

// 传统方式:写死属性名
// 方法引用:替代字符串,当属性名变化时IDE会同步提示,避免未同步产生bug
String userName = BeanUtils.convertToFieldName(User::getUserName);

具体实现代码封装:

首先我们定义1个函数式接口用来接收lambda方法引用表达式:注意函数式接口一定要继承Serializable接口才能获取方法信息。

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));
    }
}

结果如下:

通过Lambda的get方法引用拿到私有属性名

这样就大功告成了,可以使用方法引用了,再也不用担心打错字符咯。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/15222.html

(0)
小半的头像小半

相关推荐

极客之家——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!