Pergunta

Eu tenho um ArrayList e desejo de ser capaz de chamar um índice e usar a string retornada para uma chamada de método.

por exemplo.

stringList.get(2)();

Existe alguma maneira que eu poderia fazer isso?

Foi útil?

Solução

Antes de chamada que você não pode chamar um método em java sem um objeto de chamá-lo por diante. É que na lista também.

Seria melhor ter uma lista de Runnable ...

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

Se você tem o objeto que você precisa chamada, e você quiser usar a reflexão (pode ser lento) então commons em grão pode ajudar a torná-lo simples. Consulte http://commons.apache.org/beanutils

import org.apache.commons.beanutils.MethodUtils;

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

Para dar melhor eu conselho que eu precisaria saber mais sobre o problema que você está tentando resolver.

Outras dicas

Então você quer a string retornada para ser usado como o nome do método para chamar?

Você pode fazer isso usando reflexão , mas eu fortemente tinha desencorajar este.

Em vez disso você vai querer olhar para a implementação de um estratégia padrão por exemplo.

Sim , há uma maneira de usar a cadeia devolvida a partir da lista para uma chamada de método.

Como outros usuários já apontou, Você precisa usar Reflection API . Pode ser complicado lidar com isso, depende do cenário particular que você está enfrentando.

Apenas para mostrar-lhe a abordagem básica de concreto, mas exemplo simplificado , eu criar esse código. Copiá-lo e jogar mudar o índice, ea criação de novos métodos com parâmetros após aprender as noções básicas da 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...");
    }

}

Um teria que usar a reflexão. Consulte http://tutorials.jenkov.com/java-reflection/methods.html.

Será que o ArrayList Have para conter Cordas? Caso contrário, você pode preenchê-lo com casos java.lang.reflect.Method, e chamar Method.invoke () na instância retornado.

Se eu entender as suas necessidades, aqui está um exemplo baseado em uma interface; a lista, em seguida, contém implementações da interface em vez de nomes de métodos:

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 talvez polimorfismo e um método de fábrica seria uma idéia melhor. Você teria que circunscrevem os métodos que você vai ser capaz de chamar, mas que não seria uma má idéia.

Se quiser que o Monty cheio, e você estiver usando Java 6, talvez você pode criar um objeto de função JavaScript e chame-o com Rhino.

Ou se você insistir em fazer a idéia funcionar independentemente de quaisquer obstáculos, você poderia chamar para uma linguagem dinâmica como JRuby ou Clojure, sendo que ambos estão dispostos a eval() uma String.

Ou Jython ou Groovy ou ...

Em Java - de jeito nenhum. Isso não é um recurso de linguagem Java. Seu está esperando por algo como

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

Como outros sugeriram, uma solução técnica pura estaria usando reflexões: tomar a string de resultado, encontrar o método correspondente e invocá-lo. A solução técnica pode até ser um mapa como

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

e fazer algo como

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

Mas tudo isso é bom saber e você não deve usá-lo a menos que forçado ou você tem um problema concreto em que mesmo assim não tem uma solução;)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top