java反射獲取到接口和類的方法對應的參數名稱(非參數類型)

假設有方法:     

 String adminTest(String mobile,int age);

希望獲取到參數名稱:     [mobile,age]

java反射提供了很多方法,獲取所有的方法,獲取所有的參數類型等,但是卻沒有一個方法能夠幫助我們獲取方法的參數名列表。

首先:

  爲什麼我們需要獲取到方法對應的參數名稱?    

原因是例如mybatis的mapper接口中定義了很多參數名稱,在xml用佔位符來標識,就可以類似通過這種方法來一一對應,

包括spring的參數解析,這個問題是我在參考別人的手寫mybatis,中考慮到的一個問題,故貼出我查閱資料得到的方法,網上的大部分只能獲取到類的方法的參數名稱列表,對接口的方法參數名稱獲取較少.

 

其實也是基於spring中提供的類來實現的:需要jdk1.8及其以上:

在Java1.8之後,可以通過反射API java.lang.reflect.Executable.getParameters來獲取到方法參數的元信息。這要求在使用編譯器時加上-parameters參數,它會在生成的.class文件中額外存儲參數的元信息,這會增加class文件的大小。
 

idea默認是開啓的:

 

工具類:

 

 

 

package com.wm.ruanyan1.util;

import com.wm.ruanyan1.service.AdminService;
import com.wm.ruanyan1.service.UserService;
import com.wm.ruanyan1.service.impl.UserServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.util.Assert;

import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @author 半卷流年
 * @date 2020-6-20 10:12
 */
@Slf4j
public class ReflectUtil {


    /**
     * 藉助spring 的工具類,注意需要jdk8及其以上
     * 獲取方法的參數的名稱(不是類型),這個兼容接口(可以沒有實現類)  和 普通類的方法參數
     *
     * 例如:    public String test(String name,Long id);
     *
     *     獲取到的是:   [name,id]
     *
     *
     * @return
     */
    public static String[] getMethodParamName(Method method){
        Assert.notNull(method,"傳入的方法對象爲空");
        method.setAccessible(true);
        DefaultParameterNameDiscoverer discoverer = new DefaultParameterNameDiscoverer();
       return discoverer.getParameterNames(method);
    }


    /**
     * 藉助spring 的工具類,注意需要jdk8及其以上
     *      * 獲取方法的參數的名稱(不是類型),普通類的方法參數,不能獲取到接口的方法的參數名稱
     *      *
     *      * 例如:    public String test(String name,Long id);
     * @param method
     * @return
     */
    public static String[] getMethodParamNameNoInterface(Method method){
        Assert.notNull(method,"傳入的方法對象爲空");
        method.setAccessible(true);
        LocalVariableTableParameterNameDiscoverer discoverer = new LocalVariableTableParameterNameDiscoverer();
        return discoverer.getParameterNames(method);
    }


    public static void main(String[] args) throws Exception{


        /***   有實現類的接口**/
        Method test = UserService.class.getMethod("userTest", String.class, Long.class, int.class);
        String[] paramName = getMethodParamName(test);
        log.info("userService有實現類的接口方法名稱:{},方法的參數名稱:{}",test.getName(), Arrays.toString(paramName));

        /***沒有實現類的接口方法參數名稱獲取***/
        Method adminTest = AdminService.class.getMethod("adminTest", String.class, int.class);
        String[] methodParamName = getMethodParamName(adminTest);
        log.info("userService有實現類的接口方法名稱:{},方法的參數名稱:{}",adminTest.getName(), Arrays.toString(methodParamName));

        /***獲取類的方法參數名稱**/

        Method userTest = UserServiceImpl.class.getMethod("userTest", String.class, Long.class, int.class);
        String[] name = getMethodParamName(userTest);
        log.info("userService類的方法:{},方法的參數名稱:{}",adminTest.getName(), Arrays.toString(name));

        System.out.println("----------------------下面爲測試只能獲取類的方法參數名稱,獲取不到接口的方法的參數名稱---------------------------");

        /*****獲取接口的方法參數名稱******/
        String[] nameNoInterface = getMethodParamNameNoInterface(test);
        log.info("adminService有實現類的接口方法名稱:{},方法的參數名稱:{}",test.getName(), Arrays.toString(nameNoInterface));

        /***獲取類的方法參數名稱**/
        String[] noInterface = getMethodParamNameNoInterface(userTest);
        log.info("adminService類的方法:{},方法的參數名稱:{}",test.getName(), Arrays.toString(noInterface));

    }

}

 

編寫接口和實現類:

UserService

package com.wm.ruanyan1.service;

/**
 * @author 半卷流年
 * @date 2020-6-20 10:19
 */
public interface UserService {

    String userTest(String name,Long id,int count);



}

實現類:

UserServiceImpl

package com.wm.ruanyan1.service.impl;

import com.wm.ruanyan1.service.UserService;

/**
 * @author 半卷流年
 * @date 2020-6-20 10:20
 */
public class UserServiceImpl implements UserService {

    @Override
    public String userTest(String name, Long id, int count) {
        return "success";
    }
}

 

編寫一個沒有實現類的接口:

AdminService

package com.wm.ruanyan1.service;

/**
 * @author 半卷流年
 * @date 2020-6-20 10:21
 */
public interface AdminService {

    String adminTest(String mobile,int age);
}

 

測試結果:

 

 

 

可以看到成功獲取到了方法的參數名稱列表,是按照順序的

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章