java获取属性名工具

Posted lyloou

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java获取属性名工具相关的知识,希望对你有一定的参考价值。

背景

在编码时经常会用到同名的属性名字符串,比如

  1. 用相同的属性名做为 map 中的键;
  2. 在 mybatis 中,根据属性名的下划线字符串来拼接 sql 查询条件。

需要修改属性名时,如果是用字符串硬编码的,引用的地方越多,修改越困难

但是如果用的是 java8 中的属性引用,操作起来就很方便了,修改一处即可修改全部相关引用。

属性工具类测试

参考下面测试类,怎样使用;

如果想要修改 articleNamearticleTitle

在 IDEA 中,修改类的属性名很方便,选中属性名 articleName,按下快捷键 <Shift + F6>,键入新的属性名称 articleTitle,确认即可替换所有关联的属性名称


import lombok.Getter;
import lombok.Setter;

/**
 * 属性工具类测试
 *
 * @author lilou
 */
public class FieldUtilTest 

    @Setter
    @Getter
    static class Article 
        String articleName;
        String articleContent;
    

    public static void main(String[] args) 

        // test getter
        System.out.println(FieldUtil.noPrefix(Article::getArticleName));
        System.out.println(FieldUtil.underline(Article::getArticleName));
        System.out.println(FieldUtil.underlineUpper(Article::getArticleContent));
        System.out.println(FieldUtil.toSymbolCase(Article::getArticleName, '$'));


        // test setter
        System.out.println(FieldUtil.noPrefix(Article::setArticleName));
        System.out.println(FieldUtil.underline(Article::setArticleName));
        System.out.println(FieldUtil.underlineUpper(Article::setArticleContent));
        System.out.println(FieldUtil.toSymbolCase(Article::setArticleName, '$'));
    

属性工具类代码

关键逻辑是利用了 java8 中的 SerializedLambda 的 getImplMethodName 方法来获取属性名。

源码中引用了 hutool 第三方工具类的 StrUtil工具,方便操作字符串,当然也可自行开发。

参考资料:利用 Lambda 实现通过 getter/setter 方法引用拿到属性名 - SegmentFault 思否


import cn.hutool.core.util.StrUtil;

import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;

/**
 * 属性工具类,用来获取 Getter 和 Setter 属性的名称。支持首字母小写样式,下划线的样式和自定义样式
 * <p>
 * 参考:[利用Lambda实现通过getter/setter方法引用拿到属性名 - SegmentFault 思否](https://segmentfault.com/a/1190000019389160)
 *
 * @author lilou
 */
public class FieldUtil 

    /*
     * ===========> getter 方法引用 <===========
     */

    /**
     * 下划线样式,小写
     */
    public static <T> String underline(IGetter<T> fn) 
        return toSymbolCase(fn, '_');
    

    /**
     * 下划线样式,大写
     */
    public static <T> String underlineUpper(IGetter<T> fn) 
        return underline(fn).toUpperCase();
    

    /**
     * 依据符号转换样式
     */
    public static <T> String toSymbolCase(IGetter<T> fn, char symbol) 
        return StrUtil.toSymbolCase(noPrefix(fn), symbol);
    

    /***
     * 转换getter方法引用为属性名,首字母小写
     */
    public static <T> String noPrefix(IGetter<T> fn) 
        return getGeneralField(fn);
    

    /*
     * ===========> setter 方法引用 <===========
     */

    /**
     * 下划线样式,小写
     */
    public static <T, R> String underline(ISetter<T, R> fn) 
        return toSymbolCase(fn, '_');
    

    /**
     * 下划线样式,大写
     */
    public static <T, R> String underlineUpper(ISetter<T, R> fn) 
        return underline(fn).toUpperCase();
    

    /**
     * 依据符号转换样式
     */
    public static <T, R> String toSymbolCase(ISetter<T, R> fn, char symbol) 
        return StrUtil.toSymbolCase(noPrefix(fn), symbol);
    

    /**
     * 转换setter方法引用为属性名,首字母小写
     */
    public static <T, R> String noPrefix(ISetter<T, R> fn) 
        return getGeneralField(fn);
    


    /*
     * ===========> 复用功能 <===========
     */

    /**
     * 获得set或get或is方法对应的标准属性名,其它前缀的方法名使用原名
     */
    private static String getGeneralField(Serializable fn) 
        SerializedLambda lambda = getSerializedLambda(fn);
        String getOrSetMethodName = lambda.getImplMethodName();
        final String generalField = StrUtil.getGeneralField(getOrSetMethodName);
        return StrUtil.isEmpty(generalField) ? getOrSetMethodName : generalField;
    

    /***
     * 获取类对应的Lambda
     */
    private static SerializedLambda getSerializedLambda(Serializable fn) 
        //先检查缓存中是否已存在
        SerializedLambda lambda;
        try 

            //提取SerializedLambda并缓存
            Method method = fn.getClass().getDeclaredMethod("writeReplace");
            method.setAccessible(Boolean.TRUE);
            lambda = (SerializedLambda) method.invoke(fn);
         catch (Exception e) 
            throw new IllegalArgumentException("获取SerializedLambda异常, class=" + fn.getClass().getSimpleName(), e);
        
        return lambda;
    

    /**
     * getter方法接口定义
     */
    @FunctionalInterface
    public interface IGetter<T> extends Serializable 
        Object apply(T source);
    

    /**
     * setter方法接口定义
     */
    @FunctionalInterface
    public interface ISetter<T, U> extends Serializable 
        void accept(T t, U u);
    

以上是关于java获取属性名工具的主要内容,如果未能解决你的问题,请参考以下文章

java反射工具类--通过指定属性名,获取/设置对象属性值

java 使用反射获取属性名,和值

java 使用反射获取属性名,和值

java 反射机制--根据属性名获取属性值

java中遍历实体类,获取属性名和属性值

java如何循环可以可以获取到每个属性的值 ,不要用对象名.get属性名这种方式获取