Использование возвращаемой строки для вызова метода?

StackOverflow https://stackoverflow.com/questions/1803369

  •  05-07-2019
  •  | 
  •  

Вопрос

У меня есть ArrayList, и я хочу иметь возможность вызывать индекс и использовать возвращаемую строку для вызова метода.

например

stringList.get(2)();

Могу ли я как-нибудь это сделать?

Это было полезно?

Решение

Прежде всего, вы не можете вызвать метод в Java без объекта для его вызова.Это тоже есть в списке.

Было бы лучше иметь список Runnable...

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

Если у вас есть объект, который вам нужно вызвать, и вы хотите использовать отражение (может быть медленным), то компоненты commons могут помочь упростить его.Видеть http://commons.apache.org/beanutils

import org.apache.commons.beanutils.MethodUtils;

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

Чтобы дать лучший совет, мне нужно знать больше о проблеме, которую вы пытаетесь решить.

Другие советы

Итак, вы хотите, чтобы возвращаемая строка использовалась в качестве имени вызываемого метода?

Вы можете сделать это, используя отражение, но я бы категорически не рекомендовал этого делать.

Вместо этого вы захотите изучить возможность реализации шаблон стратегии например.

Да, существует способ использовать возвращаемую строку из списка для вызова метода.

Как уже отмечали другие пользователи, вам нужно использовать API отражения.С этим может быть сложно справиться, это зависит от конкретного сценария, с которым вы столкнулись.

Просто чтобы показать вам основной подход в конкретном, но упрощенный пример, я создаю этот код.Скопируйте его и играйте, меняя индекс и создавая новые методы с параметрами после изучения основ 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...");
    }

}

Придется использовать отражение.Видеть http://tutorials.jenkov.com/java-reflection/methods.html.

Имеет ли ArrayList иметь содержать строки?В противном случае вы можете заполнить его экземплярами java.lang.reflect.Method и вызвать Method.invoke() для возвращаемого экземпляра.

Если я понимаю ваши потребности, вот пример, основанный на интерфейсе;тогда список содержит реализации интерфейса, а не имена методов:

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

}

Или, может быть, полиморфизм и фабричный метод были бы лучшей идеей.Вам придется ограничить методы, которые вы сможете вызывать, но это была бы неплохая идея.

Если вам нужна полная версия Monty и вы используете Java 6, возможно, вы сможете создать объект функции JavaScript и вызвать его с помощью Rhino.

Или, если вы настаиваете на том, чтобы идея работала, несмотря ни на какие препятствия, вы можете обратиться к динамическому языку, такому как JRuby или Clojure, оба из которых готовы eval() строка.

Или Jython, или Groovy, или...

В Java - никак.Это не особенность языка Java.Вы надеетесь на что-то вроде

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

Как предлагали другие, чисто техническим решением было бы использование отражений:возьмите строку результата, найдите соответствующий метод и вызовите его.Техническим решением может быть даже карта типа

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

и сделать что-то вроде

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

но все это приятно знать, и вам не следует использовать его, если только вы не вынуждены или у вас нет конкретной проблемы, для которой даже ТАК нет решения;)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top