Как вызвать метод Java, если имя метода указано в виде строки?

"string" - это строка, которая не является нулевой. В JavaScript все значения, не равные нулю, оцениваются как «истинные». Итак: if («string») является таким же, как если бы («string»! = Null), но «string» не соответствует true, это все равно строковое значение.

638
задан Joachim Sauer 24 January 2013 в 08:20
поделиться

8 ответов

Кодируя от бедра, это было бы что-то как:

java.lang.reflect.Method method;
try {
  method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) { ... }
  catch (NoSuchMethodException e) { ... }

параметры определяют очень определенный метод, в котором Вы нуждаетесь (если существуют, несколько перегрузились доступный, если метод не имеет никаких аргументов, только дайте methodName).

Тогда Вы вызываете тот метод путем вызова

try {
  method.invoke(obj, arg1, arg2,...);
} catch (IllegalArgumentException e) { ... }
  catch (IllegalAccessException e) { ... }
  catch (InvocationTargetException e) { ... }

Снова, не учитываете аргументы в .invoke, если у Вас нет никого. Но да. Считайте [приблизительно 114] Отражение Java

917
ответ дан Andrew Tobilko 24 January 2013 в 08:20
поделиться

Чтобы завершить ответы моего коллеги, вы можете обратить пристальное внимание на:

  • статические вызовы или вызовы экземпляров (в одном случае вам не нужен экземпляр класса, в другом - вам может потребоваться существующий конструктор по умолчанию , который может или не может быть там)
  • вызов открытого или закрытого метода (для последнего, вам нужно вызвать setAccessible) для метода в блоке doPrivileged , другие findbugs не будут счастливы )
  • , инкапсулируя в еще одно управляемое аппликативное исключение, если вы хотите отбросить многочисленные исключения из системы Java ( отсюда CCException в приведенном ниже коде)

Вот старый код java1.4, который учитывает эти моменты:

/**
 * Allow for instance call, avoiding certain class circular dependencies. <br />
 * Calls even private method if java Security allows it.
 * @param aninstance instance on which method is invoked (if null, static call)
 * @param classname name of the class containing the method 
 * (can be null - ignored, actually - if instance if provided, must be provided if static call)
 * @param amethodname name of the method to invoke
 * @param parameterTypes array of Classes
 * @param parameters array of Object
 * @return resulting Object
 * @throws CCException if any problem
 */
public static Object reflectionCall(final Object aninstance, final String classname, final String amethodname, final Class[] parameterTypes, final Object[] parameters) throws CCException
{
    Object res;// = null;
    try {
        Class aclass;// = null;
        if(aninstance == null)
        {
            aclass = Class.forName(classname);
        }
        else
        {
            aclass = aninstance.getClass();
        }
        //Class[] parameterTypes = new Class[]{String[].class};
    final Method amethod = aclass.getDeclaredMethod(amethodname, parameterTypes);
        AccessController.doPrivileged(new PrivilegedAction() {
    public Object run() {
                amethod.setAccessible(true);
                return null; // nothing to return
            }
        });
        res = amethod.invoke(aninstance, parameters);
    } catch (final ClassNotFoundException e) {
        throw new CCException.Error(PROBLEM_TO_ACCESS+classname+CLASS, e);
    } catch (final SecurityException e) {
        throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_SECURITY_ISSUE, e);
    } catch (final NoSuchMethodException e) {
        throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_NOT_FOUND, e);
    } catch (final IllegalArgumentException e) {
        throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_ILLEGAL_ARGUMENTS+String.valueOf(parameters)+GenericConstants.CLOSING_ROUND_BRACKET, e);
    } catch (final IllegalAccessException e) {
        throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_ACCESS_RESTRICTION, e);
    } catch (final InvocationTargetException e) {
    throw new CCException.Error(PROBLEM_TO_ACCESS+classname+GenericConstants.HASH_DIESE+ amethodname + METHOD_INVOCATION_ISSUE, e);
    } 
    return res;
}
13
ответ дан VonC 24 January 2013 в 08:20
поделиться

Метод может быть вызван как это. Существует также больше возможностей (проверьте отражательный API), но это - самое простое:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.junit.Assert;
import org.junit.Test;

public class ReflectionTest {

    private String methodName = "length";
    private String valueObject = "Some object";

    @Test
    public void testGetMethod() throws SecurityException, NoSuchMethodException, IllegalArgumentException,
            IllegalAccessException, InvocationTargetException {
        Method m = valueObject.getClass().getMethod(methodName, new Class[] {});
        Object ret = m.invoke(valueObject, new Object[] {});
        Assert.assertEquals(11, ret);
    }



}
55
ответ дан Petr Macek 24 January 2013 в 08:20
поделиться

Во-первых, не делать. Избегайте этого вида кода. Это имеет тенденцию быть действительно плохим кодом и небезопасный также (см. раздел 6 из Безопасные Инструкции по Кодированию для Языка программирования Java, версии 2.0 ).

<забастовка>, Если необходимо сделать это, предпочтите java.beans отражению. Бобы обертывают отражение, предоставляющее относительно безопасный и стандартный доступ.

17
ответ дан Tom Hawtin - tackline 24 January 2013 в 08:20
поделиться
Object obj;

Method method = obj.getClass().getMethod("methodName", null);

method.invoke(obj, null);
12
ответ дан chickeninabiscuit 24 January 2013 в 08:20
поделиться

Это походит на что-то, что выполнимо с пакетом Отражения Java.

http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.html

Особенно под Methods Вызова по имени:

импорт java.lang.reflect.*;

public class method2 {
  public int add(int a, int b)
  {
     return a + b;
  }

  public static void main(String args[])
  {
     try {
       Class cls = Class.forName("method2");
       Class partypes[] = new Class[2];
        partypes[0] = Integer.TYPE;
        partypes[1] = Integer.TYPE;
        Method meth = cls.getMethod(
          "add", partypes);
        method2 methobj = new method2();
        Object arglist[] = new Object[2];
        arglist[0] = new Integer(37);
        arglist[1] = new Integer(47);
        Object retobj 
          = meth.invoke(methobj, arglist);
        Integer retval = (Integer)retobj;
        System.out.println(retval.intValue());
     }
     catch (Throwable e) {
        System.err.println(e);
     }
  }
}
7
ответ дан zxcv 24 January 2013 в 08:20
поделиться

Использовать вызов метода из отражения:

Class<?> c = Class.forName("class name");
Method method = c.getDeclaredMethod("method name", parameterTypes);
method.invoke(objectToInvokeOn, params);

Где:

  • "class name" - имя класса
  • objectToInvokeOn имеет тип Object и является объектом, который вы хотите вызвать методом в
  • "method name" - это имя метода, который вы хотите вызвать
  • parameterTypes, имеет тип Class[] и объявляет параметры, принимаемые методом
  • params типа Object[], и объявляет параметры, передаваемые методу
178
ответ дан Lonely Neuron 24 January 2013 в 08:20
поделиться

для меня довольно простое и надежное доказательство способом было бы просто создать метод вызывающего метода следующим образом:

public static object methodCaller(String methodName)
{
    if(methodName.equals("getName"))
        return className.getName();
}

тогда, когда вам нужно вызвать метод, просто введите что-то вроде этого

//calling a toString method is unnessary here, but i use it to have my programs to both rigid and self-explanitory 
System.out.println(methodCaller(methodName).toString()); 
-9
ответ дан 22 November 2019 в 21:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: