1. 程式人生 > >Java8新特性——反射獲取方法引數名

Java8新特性——反射獲取方法引數名

原文地址:https://blog.csdn.net/f641385712/article/details/81291273

方法的引數名,在很多時候我們是需要反射得到的。但是在java8之前,程式碼編譯為class檔案後,方法引數的型別是固定的,但引數名稱卻丟失了,這和動態語言嚴重依賴引數名稱形成了鮮明對比(java是靜態語言,所以入參名稱叫什麼其實無所謂的)。雖然名稱無所謂,但很多時候,我們需要此名稱來做更好的安排。

比如mybatis的Dao層介面方法,需要特意用個註解@Param來顯示標識出引數名,當時寫的時候我覺得挺傻X的一件事,所以java8來了,帶來的新特性解決了這一問題。

獲取方法引數名稱有以下幾種方式

方法一:採用Javassist包獲取,很麻煩,此處省略。

方法二:通過Spring的LocalVariableTableParameterNameDiscoverer。

    public static void main(String[] args) {
        List<String> paramterNames = getParamterName(StaffMark.class, "fun1");
        paramterNames.forEach((x) -> System.out.println(x));
    }

    public static void fun1(String aaa, Integer bbb) {

    }

    public static List<String> getParamterName(Class clazz, String methodName) {
        LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (methodName.equals(method.getName())) {
                //獲取到該方法的引數們
                String[] params = u.getParameterNames(method);
                return Arrays.asList(params);
            }
        }
        return null;
    }
輸出:
aaa
bbb

備註:如果不用Class,而是通過spring注入的例項,然後instance.getClass.getDeclaredMethods()則無法得到引數名,除錯時看到方法名稱是通過jdk代理過的,拿不到引數名。

方法三:通過Java8的Parameter類

現在,Java 8開始在class檔案中保留引數名,給反射帶來了極大的便利。jdk8增加了類Parameter。

除了獲取引數名稱外,還可以通過這個類獲取很多其它屬性。

    public static void main(String[] args) {
        List<String> paramterNames = getParameterNameJava8(StaffMark.class, "fun1");
        paramterNames.forEach((x) -> System.out.println(x));
    }

    public static void fun1(String aaa, Integer bbb) {

    }

    public static List<String> getParameterNameJava8(Class clazz, String methodName) {
        List<String> paramterList = new ArrayList<>();
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            if (methodName.equals(method.getName())) {
                //直接通過method就能拿到所有的引數
                Parameter[] params = method.getParameters();
                for (Parameter parameter : params) {
                    paramterList.add(parameter.getName());
                }

            }
        }

        return paramterList;
    }
輸出:
arg0
arg1

哈哈,被騙了有木有?其實並不是,因為java8為了保持向下相容,預設編譯是不能獲取到引數名稱的。需要滿足下面兩個條件

  • JDK版本必須是1.8及以上
  • 編譯時候必須有編譯選項:javac -parameters開啟,預設是關閉的

附:idea設定保留引數名:
在preferences->Java Compiler->設定模組位元組碼版本1.8,Javac Options中的 Additional command line parameters: -parameters

這樣設定之後,我們再執行上面程式碼,發現輸出的結果為:

輸出:
aaa
bbb

有了這個特性之後,以後咱們編譯的時候加上啟動引數,使用Mybatis再也不需要那煩人的@Param註解了。

原文地址:https://blog.csdn.net/f641385712/article/details/81291273