Frage

Ich habe eine Arraylist und wünschen der Lage sein, einen Index zu nennen und die zurückgegebene Zeichenfolge für einen Methodenaufruf verwendet werden.

z.

stringList.get(2)();

Gibt es eine Weise, die ich über diese gehen könnte?

War es hilfreich?

Lösung

Als erstes Anruf Sie keine Methode in Java ohne ein Objekt aufrufen kann es rufen. Ist das in der Liste auch.

Es wäre besser, eine Liste von Runnable zu haben ...

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

Wenn Sie das Objekt haben Sie anrufen müssen, und Sie wollen Reflexion verwenden (kann langsam sein), dann commons-Bohnen kann es einfach helfen machen. Siehe http://commons.apache.org/beanutils

import org.apache.commons.beanutils.MethodUtils;

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

besser zu geben, ich beraten würde ich brauchen würde, um mehr über das Problem zu wissen, dass Sie versuchen zu lösen.

Andere Tipps

So können Sie das zurückgegebene String wollen, wie der Name des Verfahrens verwendet werden, zu nennen?

Das können Sie mit Reflexion , aber ich würde stark entmutigen dies.

Stattdessen wollen Sie schauen Strategie-Muster zum Beispiel Umsetzung.

Ja , gibt es einen Weg, um den zurückgegebenen String aus der Liste für einen Methodenaufruf zu verwenden.

Wie andere Benutzer bereits darauf hingewiesen, Sie verwenden müssen, Reflection-API . Kann Deal mit, dass kompliziert sein, hängt von dem jeweiligen Szenario Sie konfrontiert sind.

Nur dir den grundlegenden Ansatz in einem konkreten zu zeigen, aber vereinfachtes Beispiel , erstelle ich diesen Code. Kopieren Sie sie und spielen um den Index zu ändern, und neue Methoden mit Parametern zu schaffen, nachdem die Grundlagen der API lernen.

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...");
    }

}

Man müßte Reflexion verwenden. Siehe http://tutorials.jenkov.com/java-reflection/methods.html.

Hat der Arraylist wurde Strings enthalten? Sonst könnte man es mit Methode von java.lang.reflect Instanzen bevölkert, und ruft Method.invoke () auf der zurückgegebenen Instanz.

Wenn ich Ihre Bedürfnisse zu verstehen, hier ist ein Beispiel für eine Schnittstelle basiert; Die folgende Liste enthält dann Implementierungen der Schnittstelle statt Methodennamen:

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(); 
    }

}

Vielleicht Polymorphismus und ein Factory-Methode wäre eine bessere Idee. Sie würden die Methoden umschreiben müssen Sie in der Lage sein zu nennen, aber das wäre keine schlechte Idee sein.

Wenn Sie die volle Monty wollen, und Sie verwenden Java 6, vielleicht können Sie eine JavaScript-Funktion Objekt erstellen und rufen Sie es mit Rhino.

Oder wenn Sie darauf, die Idee der Arbeit unabhängig von irgendwelchen Hindernissen bestehen, könnten Sie zu einer dynamischen Sprache wie JRuby oder Clojure rufen, beide sind bereit, einen String eval().

oder Jython oder Groovy oder ...

In Java - auf keinen Fall. Das ist keine Java-Sprache-Funktion. Your're der Hoffnung für so etwas wie

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

Wie andere vorgeschlagen, eine reine technische Lösung würde Reflexionen werden: das Ergebnis String nehmen, die entsprechende Methode finden und aufzurufen. Eine technische Lösung könnte sogar eine Karte sein, wie

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

und tun so etwas wie

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

aber all das ist schön zu wissen, und Sie sollten es nicht benutzen, es sei denn gezwungen, oder Sie haben ein konkretes Problem, bei dem selbst dann keine Lösung haben;)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top