150 votes

Puis-je obtenir le nom du paramètre de la méthode en utilisant la réflexion Java ?

Si j'ai un cours comme ça :

public class Whatever
{
  public void aMethod(int aParam);
}

Y a-t-il un moyen de savoir que aMethod utilise un paramètre nommé aParam qui est de type int ?

11 votes

7 réponses et personne n'a mentionné le terme "signature de méthode". C'est essentiellement ce que vous pouvez introspecter avec la réflexion, ce qui signifie : pas de noms de paramètres.

3 votes

Il est possible, voir ma réponse ci-dessous

7 votes

6 ans plus tard, c'est désormais possible via la réflexion en Java 8 voir cette réponse SO

123voto

lpandzic Points 399

En Java 8, vous pouvez faire ce qui suit :

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;

public final class Methods {

    public static List<String> getParameterNames(Method method) {
        Parameter[] parameters = method.getParameters();
        List<String> parameterNames = new ArrayList<>();

        for (Parameter parameter : parameters) {
            if(!parameter.isNamePresent()) {
                throw new IllegalArgumentException("Parameter names are not present!");
            }

            String parameterName = parameter.getName();
            parameterNames.add(parameterName);
        }

        return parameterNames;
    }

    private Methods(){}
}

Donc pour votre classe Whatever nous pouvons faire un test manuel :

import java.lang.reflect.Method;

public class ManualTest {
    public static void main(String[] args) {
        Method[] declaredMethods = Whatever.class.getDeclaredMethods();

        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.getName().equals("aMethod")) {
                System.out.println(Methods.getParameterNames(declaredMethod));
                break;
            }
        }
    }
}

qui devrait imprimer [aParam] si vous avez passé -parameters à votre compilateur Java 8.

Pour les utilisateurs de Maven :

<properties>
    <!-- PLUGIN VERSIONS -->
    <maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>

    <!-- OTHER PROPERTIES -->
    <java.version>1.8</java.version>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven-compiler-plugin.version}</version>
            <configuration>
                <!-- Original answer -->
                <compilerArgument>-parameters</compilerArgument>
                <!-- Or, if you use the plugin version >= 3.6.2 -->
                <parameters>true</parameters>
                <testCompilerArgument>-parameters</testCompilerArgument>
                <source>${java.version}</source>
                <target>${java.version}</target>
            </configuration>
        </plugin>
    </plugins>
</build>

Pour plus d'informations, voir les liens suivants :

  1. Tutoriel officiel de Java : Obtenir le nom des paramètres d'une méthode
  2. JEP 118 : Accès aux noms de paramètres à l'exécution
  3. Javadoc pour la classe Parameter

2 votes

Je ne sais pas s'ils ont changé les arguments pour le plugin de compilateur, mais avec la dernière (3.5.1 à partir de maintenant) j'ai dû faire pour utiliser les args de compilateur dans la section de configuration : <configuration> <compilerArgs> <arg>-paramètres</arg> </compilerArgs> </configuration>.

0 votes

C'est vraiment utile !

109voto

Bozho Points 273663

Pour résumer :

  • obtenir les noms des paramètres est possible si les informations de débogage sont incluses lors de la compilation. Voir cette réponse pour plus de détails
  • sinon, obtenir les noms des paramètres est pas possible
  • obtenir le type de paramètre est possible, en utilisant method.getParameterTypes()

Pour écrire une fonctionnalité de complétion automatique pour un éditeur (comme vous l'avez indiqué dans l'un des commentaires), il existe quelques options :

  • utiliser arg0 , arg1 , arg2 etc.
  • utiliser intParam , stringParam , objectTypeParam etc.
  • utiliser une combinaison des éléments ci-dessus - le premier pour les types non primitifs, et le second pour les types primitifs.
  • ne montrent pas du tout les noms des arguments - seulement les types.

4 votes

Est-ce possible avec les interfaces ? Je n'ai toujours pas trouvé le moyen d'obtenir les noms des paramètres des interfaces.

0 votes

@Cemo : avez-vous réussi à trouver un moyen d'obtenir les noms des paramètres d'interface ?

1 votes

Juste pour ajouter, c'est pourquoi Spring a besoin de l'annotation @ConstructorProperties pour créer sans ambiguïté des objets à partir de types primitifs.

15voto

Sarel Botha Points 5911

La bibliothèque Paranamer a été créée pour résoudre ce même problème.

Il tente de déterminer les noms des méthodes de plusieurs manières différentes. Si la classe a été compilée avec débogage, il peut extraire les informations en lisant le bytecode de la classe.

Une autre méthode consiste à injecter un membre statique privé dans le bytecode de la classe après sa compilation, mais avant qu'elle ne soit placée dans un jar. Il utilise ensuite la réflexion pour extraire cette information de la classe au moment de l'exécution.

https://github.com/paul-hammant/paranamer

J'ai eu des difficultés à utiliser cette bibliothèque, mais j'ai fini par la faire fonctionner. J'espère pouvoir signaler les problèmes au mainteneur.

0 votes

J'essaie d'utiliser paranamer dans un apk Android. Mais j'obtiens ParameterNAmesNotFoundException

3voto

Johnco Points 1389

Vous pouvez récupérer la méthode avec la réflexion et détecter ses types d'arguments. Vérifiez [getParameterTypes()](https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/reflect/Method.html#getParameterTypes()) .

Cependant, vous ne pouvez pas connaître le nom de l'argument utilisé.

19 votes

Vraiment, c'est tout à fait possible. Sa question était cependant explicitement sur le nom du paramètre . Vérifiez le titre du sujet.

1 votes

Et je cite : "Cependant, vous ne pouvez pas dire le nom de l'argument utilisé." lisez juste ma réponse -_-

3 votes

La question n'était pas formulée de cette façon, il ne savait pas comment obtenir le type.

3voto

flybywire Points 36050

C'est possible et Spring MVC 3 le fait, mais je n'ai pas pris le temps de voir exactement comment.

La correspondance des noms de paramètres de méthode aux noms de variables URI Template ne peut seulement si votre code est compilé avec le débogage activé. Si vous n'avez pas activé le débogage, vous devez spécifier le nom du modèle URI dans l'annotation @PathVariable afin de lier la valeur valeur résolue du nom de la variable à un paramètre de méthode. Par exemple :

Tiré du documentation sur le printemps

0 votes

Org.springframework.core.Conventions.getVariableName() mais je suppose que vous devez avoir cglib comme dépendance.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X