Usando uma corda voltou a chamar um método?
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?
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;)