前言
在开发过程中,很多开发场景需要用到Java Bean的属性名,但是直接采用字符串写死属性名的形式容易产生问题,属性名一旦变化,我们可能会忘记修改对应的属性名,且编译器不会告诉你你的字符串需要同步修改。不过,JDK8的Lambda可以通过方法引用简化代码,同样也可以通过getter/setter的方法引用拿到属性名,从而避免潜在的bug。
实现步骤
Get方式
编写函数式接口
@FunctionalInterface
public interface IGetter<T> extends Serializable {
Object apply(T source);
}
编写工具类
@Slf4j
public class EntityUtil {
/**
* 缓存类-Lambda的映射关系
*/
private static Map<Class, SerializedLambda> CLASS_LAMDBA_CACHE = new ConcurrentHashMap<>();
/***
* 转换方法引用为属性名
* @param fn
* @return
*/
public static <T> String convertToFieldName(IGetter<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) {
log.warn("无效的getter方法: " + methodName);
}
// 截取get/is之后的字符串并转换首字母为小写,自己实现对应的功能
return StrUtil.lowerFirst(StrUtil.removeAll(methodName, prefix));
}
// 获取方法名
public static <T> String getMethodName(IGetter<T> fn) {
SerializedLambda lambda = getSerializedLambda(fn);
// 获取方法名
return lambda.getImplMethodName();
}
/***
* 获取类对应的Lambda
* @param fn
* @return
*/
private 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) {
log.error("获取SerializedLambda异常, class=" + fn.getClass().getSimpleName(), e);
}
}
return lambda;
}
}
使用方式
System.out.println(EntityUtil.convertToFieldName(LayerQueryForm::getCityCode));
System.out.println(EntityUtil.getMethodName(LayerQueryForm::getCityCode));
输出结果
cityCode
getCityCode
Set方式
原理类似,故省略....




