Domanda

Ho un ArrayList e desidero poter chiamare un indice e utilizzare la stringa restituita per una chiamata al metodo.

per es.

stringList.get(2)();

Esiste un modo per fare questo?

È stato utile?

Soluzione

Prima di chiamare non è possibile chiamare un metodo in Java senza un oggetto su cui richiamarlo. È presente anche nell'elenco.

Sarebbe meglio avere un elenco di Runnable ...

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

Se hai l'oggetto che devi chiamare e vuoi usare il reflection (può essere lento), i commons-bean possono aiutarti a renderlo semplice. Vedi http://commons.apache.org/beanutils

import org.apache.commons.beanutils.MethodUtils;

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

Per dare un consiglio migliore consiglierei di saperne di più sul problema che stai cercando di risolvere.

Altri suggerimenti

Quindi vuoi che la stringa restituita sia usata come nome del metodo da chiamare?

Puoi farlo usando reflection , ma farei scoraggiare questo.

Invece vorrai esaminare l'implementazione di un modello di strategia per esempio.

, esiste un modo per utilizzare la stringa restituita dall'elenco per una chiamata al metodo.

Come già sottolineato da altri utenti, devi utilizzare API di riflessione . Può essere complicato affrontarlo, dipende dallo scenario particolare che stai affrontando.

Solo per mostrarti l'approccio di base in un esempio concreto ma semplificato , creo questo codice. Copialo e gioca cambiando l'indice e creando nuovi metodi con parametri dopo aver appreso le basi dell'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...");
    }

}

Uno dovrebbe usare la riflessione. Vedi http://tutorials.jenkov.com/java-reflection/methods.html.

ArrayList deve contenere stringhe? Altrimenti potresti popolarlo con istanze java.lang.reflect.Method e chiamare Method.invoke () sull'istanza restituita.

Se capisco le tue esigenze, ecco un esempio basato su un'interfaccia; l'elenco contiene quindi implementazioni dell'interfaccia anziché nomi di metodi:

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

}

O forse il polimorfismo e un metodo di fabbrica sarebbero un'idea migliore. Dovresti circoscrivere i metodi che sarai in grado di chiamare, ma non sarebbe una cattiva idea.

Se vuoi l'intero Monty e stai usando Java 6, forse puoi creare un oggetto funzione JavaScript e invocarlo con Rhino.

O se insisti nel far funzionare l'idea indipendentemente da eventuali ostacoli, potresti chiamare un linguaggio dinamico come JRuby o Clojure, entrambi disposti a eval () una stringa.

O Jython o Groovy o ...

In Java - assolutamente no. Questa non è una funzione del linguaggio Java. Stai sperando in qualcosa di simile

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

Come altri hanno suggerito, una soluzione tecnica pura sarebbe usare i riflessi: prendere la stringa del risultato, trovare il metodo corrispondente e invocarlo. Una soluzione tecnica potrebbe persino essere una mappa come

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

e fai qualcosa come

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

ma tutto ciò è bello da sapere e non dovresti usarlo se non forzato o hai un problema concreto in cui anche SO non ha una soluzione;)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top