By Lambda get method to get a reference to private property name

Preface:

Recently the use of mybatis-plus framework, we all know that there is such a kind of writing, you can get the property value by reference methods lambda avoid large numbers of mana

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

For such implementations mybatis-plus bloggers have already written, do not understand can refer blog.csdn.net/u012503481/... this article

Then we certainly need to use a lot of development scenarios of Java Bean property name, write directly in the form of dead property name string prone to bug (once attribute name change, IDE will not tell you you need to synchronize string modification). The method JDK8 Lambda by reference to simplify the code, reference can also get the property name by a method getter / setter avoid potential bug.

To achieve the desired effect:

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

Specific implementation code Package:

First we define a function interface for receiving lambda expressions method references: Note function interface must inherit Serializable interface in order to obtain information method.

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);
}
复制代码

Secondly, we realize a reference tool getter class conversion attribute name [note basically write Well, a little not understand the words, Baidu, self]

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

}
复制代码

test:

Briefly create an entity class

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;
    }
}
复制代码

Then try to call

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

复制代码

The results are as follows:

That's it, you can use references, no longer have to worry about the wrong character slightly.


Guess you like

Origin juejin.im/post/5d8c22416fb9a04dd95e6ce8