Как я могу вызвать метод из строки? [Дубликат]

[D2] Да.

См. [D0] Руководство по разветвлению и объединению Visual Studio TFS для некоторых замечательных информация о рекомендуемых методах ветвления.

Или Как: Файлы и папки филиала (MSDN) для более явных инструкций по созданию этого диалога для создания ветки.

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

17 ответов

Кодирование с тазобедренного сустава было бы примерно таким:

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, если у вас их нет. Но да. Читайте о Java Reflection

835
ответ дан Andrew Tobilko 16 August 2018 в 04:30
поделиться
  • 1
    Было немного расстроено тем фактом, что Java использует стирание стилей, но зная, что, по крайней мере, Reflection снова подбадривает меня: D И теперь с lambdas на Java 8 язык действительно ускоряется с современной разработкой. Единственное, чего сейчас нет, это встроенная поддержка getters и seters или свойств, поскольку они известны на C #. – 7hi4g0 1 April 2014 в 14:23
  • 2
    Не справедливо -1. Хенрик, вероятно, не выступает за раздачу исключений и ничего не пишет для них, потому что он просто пытается продемонстрировать свое отражение. – drew 21 May 2014 в 21:52
  • 3
    Плюс один для отображения некоторых возможных исключений. Если бы я написал это, это было бы ... catch (Exception e) {... – mikbanUtah 11 December 2014 в 07:32
  • 4
    Я получил «переменную», возможно, не был инициализирован ». для method в method.invoke(obj, arg1, arg2,...);. a method = null; решает проблему, но упоминание об этом в ответе - неплохая идея. – Amin 14 February 2016 в 19:14
  • 5
    @ DeaMon1 Java-методы не используют «коды выхода», но если метод возвращает что-либо, invoke вернет все, что он вернул. Если при запуске метода возникает исключение, исключение будет обернуто в InvocationTargetException. – ThePyroEagle 22 December 2016 в 16:28
//Step1 - Using string funClass to convert to class
String funClass = "package.myclass";
Class c = Class.forName(funClass);

//Step2 - instantiate an object of the class abov
Object o = c.newInstance();
//Prepare array of the arguments that your function accepts, lets say only one string here
Class[] paramTypes = new Class[1];
paramTypes[0]=String.class;
String methodName = "mymethod";
//Instantiate an object of type method that returns you method name
 Method m = c.getDeclaredMethod(methodName, paramTypes);
//invoke method with actual params
m.invoke(o, "testparam");
10
ответ дан anujin 16 August 2018 в 04:30
поделиться
Object obj;

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

method.invoke(obj, null);
8
ответ дан chickeninabiscuit 16 August 2018 в 04:30
поделиться
  • 1
    Произошла ошибка. obj должно быть инициализировано. – Keval Trivedi 27 June 2014 в 11:30
  • 2
    Объект должен иметь как минимум значение / значения. – Lova Chittumuri 12 February 2018 в 15:38

Если вы выполняете вызов несколько раз, вы можете использовать новые дескрипторы методов, введенные в Java 7. Здесь мы переходим к тому, чтобы ваш метод возвращал строку:

Object obj = new Point( 100, 200 );
String methodName = "toString";  
Class<String> resultType = String.class;

MethodType mt = MethodType.methodType( resultType );
MethodHandle methodHandle = MethodHandles.lookup().findVirtual( obj.getClass(), methodName, mt );
String result = resultType.cast( methodHandle.invoke( obj ) );

System.out.println( result );  // java.awt.Point[x=100,y=200]
6
ответ дан Christian Ullenboom 16 August 2018 в 04:30
поделиться
  • 1
    Будущим читателям; Если вы заботитесь о производительности, вы будете использовать invokeExact, когда сможете. Для этого подпись сайта вызова должна точно соответствовать типу дескриптора метода. Обычно требуется немного возиться, чтобы работать. В этом случае вам нужно будет указать первый параметр с помощью: methodHandle = methodHandle.asType(methodHandle.type().changeParameterType(0, Object.class));, а затем вызвать как String result = (String) methodHandle.invokeExact(obj); – Jorn Vernee 4 February 2018 в 13:09

, используя import java.lang.reflect.*;

public static Object launchProcess(String className, String methodName, Class<?>[] argsTypes, Object[] methodArgs)
        throws Exception {

    Class<?> processClass = Class.forName(className); // convert string classname to class
    Object process = processClass.newInstance(); // invoke empty constructor

    Method aMethod = process.getClass().getMethod(methodName,argsTypes);
    Object res = aMethod.invoke(process, methodArgs); // pass arg
    return(res);
}

, и вот как вы его используете:

String className = "com.example.helloworld";
String methodName = "print";
Class<?>[] argsTypes = {String.class,  String.class};
Object[] methArgs = { "hello", "world" };   
launchProcess(className, methodName, argsTypes, methArgs);
1
ответ дан dina 16 August 2018 в 04:30
поделиться

Я делаю это вот так:

try {
    YourClass yourClass = new YourClass();
    Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
    method.invoke(yourClass, parameter);
} catch (Exception e) {
    e.printStackTrace();
}
158
ответ дан Lonely Neuron 16 August 2018 в 04:30
поделиться
  • 1
    Прохладный, я думаю, что вы правы с getDeclaredMethod (), вероятно, это «безопаснее», чем getMethod () .. – brasskazoo 2 October 2008 в 06:40
  • 2
    Неправильно. Да, getDeclaredMethod действительно работает с частными и защищенными методами. НО: он не работает с методами, определенными в суперклассах (унаследованные методы). Таким образом, это сильно зависит от того, что вы хотите сделать. Во многих случаях вы хотите, чтобы он работал независимо от точного класса, в котором определяется метод. – jrudolph 2 October 2008 в 10:12
  • 3
    И где я должен поставить «класс»? файл? желательно объяснить для Eclipse IDE – Mr.Hyde 8 August 2016 в 11:04
  • 4
    @ Mr.Hyde на пути к классу. – Stijn de Witt 9 March 2017 в 12:31

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

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
ответ дан lpapp 16 August 2018 в 04:30
поделиться
  • 1
    Если экземпляр уже известен во время компиляции, почему бы вам просто не сделать className.getName().toString()? Вам не хватает всей точки зрения. – BalusC 16 June 2010 в 21:31
  • 2
    Как я уже сказал, в этом случае лишний, но предполагая, что вы всегда будете знать, что экземпляр - плохая привычка программирования. – SMayne 17 June 2010 в 18:19
  • 3
    @SMayne: Я бы предложил удалить этот пост. – lpapp 18 April 2014 в 16:11
  • 4
    плохое программирование скорее будет комплиментом в этом случае – pdenti 12 December 2014 в 19:57

Это отлично работает для меня:

public class MethodInvokerClass {
    public static void main(String[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, ClassNotFoundException, InvocationTargetException, InstantiationException {
        Class c = Class.forName(MethodInvokerClass.class.getName());
        Object o = c.newInstance();
        Class[] paramTypes = new Class[1];
        paramTypes[0]=String.class;
        String methodName = "countWord";
         Method m = c.getDeclaredMethod(methodName, paramTypes);
         m.invoke(o, "testparam");
}
public void countWord(String input){
    System.out.println("My input "+input);
}

}

Выход:

My input testparam

Я могу для вызова метода путем передачи его имени другому методу (например, main).

1
ответ дан Luke H 16 August 2018 в 04:30
поделиться

Вы должны использовать reflection - init объект класса, затем метод в этом классе, а затем вызвать этот метод для объекта с параметрами optional . Не забудьте обернуть следующий фрагмент в блок try-catch

Надеюсь, что это поможет!

Class<?> aClass = Class.forName(FULLY_QUALIFIED_CLASS_NAME);
Method method = aClass.getMethod(methodName, YOUR_PARAM_1.class, YOUR_PARAM_2.class);
method.invoke(OBJECT_TO_RUN_METHOD_ON, YOUR_PARAM_1, YOUR_PARAM_2);
1
ответ дан nurxyz 16 August 2018 в 04:30
поделиться

Метод может быть вызван следующим образом. Есть также больше возможностей (проверьте отражение 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);
    }



}
51
ответ дан Petr Macek 16 August 2018 в 04:30
поделиться
  • 1
    +1 для единственного ответа, который признал, что ОП задает «без параметров», в его вопросе (и потому, что это то, что я искал тоже). – John Fitzpatrick 17 January 2013 в 19:54

Пожалуйста, обратитесь к следующему коду, который может вам помочь.

public static Method method[];
public static MethodClass obj;
public static String testMethod="A";

public static void main(String args[]) 
{
    obj=new MethodClass();
    method=obj.getClass().getMethods();
    try
    {
        for(int i=0;i<method.length;i++)
        {
            String name=method[i].getName();
            if(name==testMethod)
            {   
                method[i].invoke(name,"Test Parameters of A");
            }
        }
    }
    catch(Exception ex)
    {
        System.out.println(ex.getMessage());
    }
}

Спасибо ....

4
ответ дан Rahul Karankal 16 August 2018 в 04:30
поделиться
  • 1
    Спасибо @Guss за необходимые изменения в коде .... – Rahul Karankal 10 August 2017 в 09:06

Для тех, кому нужен пример прямого кода в Java 7:

Dog класс:

package com.mypackage.bean;

public class Dog {
    private String name;
    private int age;

    public Dog() {
        // empty constructor
    }

    public Dog(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void printDog(String name, int age) {
        System.out.println(name + " is " + age + " year(s) old.");
    }
}

ReflectionDemo класс:

package com.mypackage.demo;

import java.lang.reflect.*;

public class ReflectionDemo {

    public static void main(String[] args) throws Exception {
        String dogClassName = "com.mypackage.bean.Dog";
        Class<?> dogClass = Class.forName(dogClassName); // convert string classname to class
        Object dog = dogClass.newInstance(); // invoke empty constructor

        String methodName = "";

        // with single parameter, return void
        methodName = "setName";
        Method setNameMethod = dog.getClass().getMethod(methodName, String.class);
        setNameMethod.invoke(dog, "Mishka"); // pass arg

        // without parameters, return string
        methodName = "getName";
        Method getNameMethod = dog.getClass().getMethod(methodName);
        String name = (String) getNameMethod.invoke(dog); // explicit cast

        // with multiple parameters
        methodName = "printDog";
        Class<?>[] paramTypes = {String.class, int.class};
        Method printDogMethod = dog.getClass().getMethod(methodName, paramTypes);
        printDogMethod.invoke(dog, name, 3); // pass args
    }
}

Выход: Mishka is 3 year(s) old.


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

Constructor<?> dogConstructor = dogClass.getConstructor(String.class, int.class);
Object dog = dogConstructor.newInstance("Hachiko", 10);

В качестве альтернативы вы можете удалить

String dogClassName = "com.mypackage.bean.Dog";
Class<?> dogClass = Class.forName(dogClassName);
Object dog = dogClass.newInstance();

и do

Dog dog = new Dog();

Method method = Dog.class.getMethod(methodName, ...);
method.invoke(dog, ...);

Предлагаемое чтение: Создание новых экземпляров класса

65
ответ дан silver 16 August 2018 в 04:30
поделиться

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

Если вы должны это сделать, предпочитайте java .beans to reflection. Бобы обертывают отражение, обеспечивая относительно безопасный и обычный доступ.

16
ответ дан Tom Hawtin - tackline 16 August 2018 в 04:30
поделиться
  • 1
    Я не согласен. Очень легко написать такой код для обеспечения безопасности, и я сделал это на нескольких языках. Например, можно было бы создать набор допустимых методов и разрешить только метод, если он указан в наборе. Еще более безопасная (но все же простая голова) ограничивает каждый разрешенный метод конкретным состоянием и не позволяет вызывать метод, если только нить / интерфейс / пользователь / что-либо не соответствует таким критериям. – JSON 9 February 2015 в 10:39

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

  • статические вызовы или вызовы экземпляров (в одном случае вам не нужен экземпляр класса, в другом , вам может потребоваться полагаться на существующий конструктор по умолчанию, который может быть или не быть там)
  • общедоступный или непубличный вызов метода (для последнего вам нужно вызвать setAccessible для метода в пределах doPrivileged block , другие 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;
}
12
ответ дан VonC 16 August 2018 в 04:30
поделиться

Это похоже на то, что можно сделать с пакетом Java Reflection.

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

В частности, при вызове методов по имени:

import 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);
     }
  }
}
6
ответ дан zxcv 16 August 2018 в 04:30
поделиться
159
ответ дан Lonely Neuron 6 September 2018 в 03:09
поделиться
164
ответ дан Lonely Neuron 29 October 2018 в 09:52
поделиться
Другие вопросы по тегам:

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