Question

J'ai une liste de tableaux et je souhaite pouvoir appeler un index et utiliser la chaîne renvoyée pour un appel de méthode.

par exemple

stringList.get(2)();

Existe-t-il un moyen de remédier à cela?

Était-ce utile?

La solution

Tout d’abord, vous ne pouvez pas appeler une méthode en Java sans objet pour l’appeler. Est-ce que dans la liste aussi.

Il serait préférable d’avoir une liste de Runnable ...

List<Runnable> runnables = ...
runnables.get(2).call();

Si vous avez l’objet que vous devez appeler et que vous souhaitez utiliser la réflexion (peut être lent), commons-beans peut vous aider à simplifier les choses. Voir http://commons.apache.org/beanutils

import org.apache.commons.beanutils.MethodUtils;

Object target = ...
List<String> methodNames = ...
MethodUtils.invokeMethod(target, methodNames.get(2), /*args*/ null);

Pour mieux vous conseiller, je voudrais en savoir plus sur le problème que vous essayez de résoudre.

Autres conseils

Vous voulez donc que la chaîne retournée soit utilisée comme nom de la méthode à appeler?

Vous pouvez le faire en utilisant réflexion , mais je voudrais vivement décourager cela.

Au lieu de cela, vous voudrez peut-être envisager de mettre en place un modèle de stratégie , par exemple.

Oui , vous pouvez utiliser la chaîne renvoyée dans la liste pour un appel de méthode.

Comme d'autres utilisateurs l'ont déjà souligné, vous devez utiliser API de réflexion . Cela peut être compliqué, cela dépend du scénario auquel vous êtes confronté.

Juste pour vous montrer l'approche de base dans un exemple concret mais simplifié , je crée ce code. Copiez-le et lisez-le en changeant l'index et en créant de nouvelles méthodes avec des paramètres après avoir appris les bases de l'API.

import java.lang.reflect.*;
import java.util.*;

public class DemoReflection {

    public static void main(String[] args) {

        List<String> myStringList = new ArrayList<String>();
        myStringList.add(0, "foo");
        myStringList.add(1, "printStr");
        myStringList.add(2, "otherMethod");
        myStringList.add(3, "stackoverflow");

        int index = 3;
        String methodName = myStringList.get(index);

        try {
            Class<?> c = Class.forName("DemoReflection");
            Object obj = c.newInstance();

            Method method = c.getDeclaredMethod(methodName, null);
            method.invoke(obj, null);

        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }

      }

    public void stackoverflow() {
         System.out.println("Stackoverflow rules!");
    }

    public void printStr() {
         System.out.println("Method printStr invoked...");
    }

}

Il faudrait utiliser la réflexion. Voir http://tutorials.jenkov.com/java-reflection/methods.html.

ArrayList doit-il contenir des chaînes? Sinon, vous pouvez le renseigner avec les instances de java.lang.reflect.Method et appeler Method.invoke () sur l'instance renvoyée.

Si je comprends vos besoins, voici un exemple basé sur une interface; la liste contient alors des implémentations de l'interface plutôt que des noms de méthodes:

import java.util.ArrayList;
import java.util.List;

public class Test {

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

        List<Action> actions = new ArrayList<Action>();
        actions.add(new Action(){
            public void execute() {
                System.out.println("Action 0");
            }});
        actions.add(new Action(){
            public void execute() {
                System.out.println("Action 1");
            }});

        actions.get(0).execute();
        actions.get(1).execute();

    }


    static interface Action{ 
        void execute(); 
    }

}

Ou peut-être un polymorphisme et une méthode d'usine seraient une meilleure idée. Vous devrez limiter les méthodes que vous pourrez appeler, mais ce ne serait pas une mauvaise idée.

Si vous voulez la version complète de Monty et que vous utilisez Java 6, vous pouvez peut-être créer un objet fonction JavaScript et l'appeler avec Rhino.

Ou si vous insistez pour que l'idée fonctionne, quels que soient les obstacles, vous pouvez faire appel à un langage dynamique tel que JRuby ou Clojure, qui sont tous deux disposés à eval () par String.

Ou Jython ou Groovy ou ...

En Java, c'est impossible. Ce n'est pas une fonctionnalité du langage Java. Vous espérez quelque chose comme

// NOT VALID JAVA
String myColoring = paintBlackOrWhite() ? "black" : "white";
myColoring(myBathroomWall);
// NOT VALID JAVA

Comme d'autres l'ont suggéré, une solution purement technique consisterait à utiliser les réflexions: prenez la chaîne de résultat, recherchez la méthode correspondante et appelez-la. Une solution technique pourrait même être une carte comme

Map<String, java.lang.reflect.Method> myMethods;

et faire quelque chose comme

get("black").invoke(myObject, myParams);

mais tout cela est bon à savoir et vous ne devriez pas l'utiliser sauf si vous y êtes forcé ou si vous avez un problème concret où même SO n'a pas de solution;)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top