当方法名作为字符串给定时,如何调用Java方法?

当方法名作为字符串给定时,如何调用Java方法?,java,reflection,invoke,Java,Reflection,Invoke,如果我有两个变量: Object obj; String methodName = "getName"; 在不知道obj的类的情况下,如何调用由其上的methodName标识的方法 正在调用的方法没有参数,并且有一个字符串返回值。它是Java bean的获取工具。使用反射: Class<?> c = Class.forName("class name"); Method method = c.getDeclaredMethod("method name", parameterTyp

如果我有两个变量:

Object obj;
String methodName = "getName";
在不知道obj的类的情况下,如何调用由其上的methodName标识的方法

正在调用的方法没有参数,并且有一个字符串返回值。它是Java bean的获取工具。

使用反射:

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

类名是类的名称 objectToInvokeOn属于Object类型,是要在其上调用方法的对象 method name是要调用的方法的名称 parameterTypes的类型为类[],并声明该方法采用的参数 params的类型为Object[],并声明要传递给方法的参数
这听起来像是Java反射包可以实现的

特别是在按名称调用方法时:

导入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);
     }
  }
}

从臀部开始编码,可能是这样的:

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中的参数。但是是的。阅读

该方法可以这样调用。还有更多的可能性检查反射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);
    }



}

要完成我同事的回答,您可能需要密切关注:

静态或实例调用在一种情况下,您不需要类的实例,在另一种情况下,您可能需要依赖现有的默认构造函数,该构造函数可能存在,也可能不存在 公共或非公共方法调用对于后者,您需要在doPrivileged块内的方法上调用setAccessible,其他 如果您想抛出大量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;
}

首先,不要。避免这种代码。它往往是非常糟糕的代码和不安全的,请参见第6节


如果必须这样做,请选择java.bean而不是反射。Beans封装了反射,允许相对安全和常规的访问。

对我来说,一个非常简单和简单的方法就是简单地创建一个方法调用方方法,如下所示:

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

对于那些想要Java 7中直截了当的代码示例的人:

狗类:

ReflectionDemo类:

或者,您可以删除

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

建议阅读:

您应该在类对象中使用reflection-init,然后在此类中使用方法,然后在具有可选参数的对象上调用此方法。记住在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);

这对我来说很好:

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

输出:

我的输入testparam


我可以通过将其名称传递给另一个方法(如main)来调用该方法。

请参阅以下代码,这些代码可能会对您有所帮助

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

我是这样做的:

try {
    YourClass yourClass = new YourClass();
    Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
    method.invoke(yourClass, parameter);
} catch (Exception e) {
    e.printStackTrace();
}
使用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);
     }
  }
}
以下是您如何使用它:

String className = "com.example.helloworld";
String methodName = "print";
Class<?>[] argsTypes = {String.class,  String.class};
Object[] methArgs = { "hello", "world" };   
launchProcess(className, methodName, argsTypes, methArgs);

SomeClass是类,someVariable是变量。

如果多次调用,可以使用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]
Student.java StudentTest.java
以下是可随时使用的方法:

要调用不带参数的方法,请执行以下操作:

要使用参数调用方法,请执行以下操作:

使用上述方法如下:

package practice;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

public class MethodInvoke {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
        String methodName1 = "methodA";
        String methodName2 = "methodB";
        MethodInvoke object = new MethodInvoke();
        callMethodByName(object, methodName1);
        callMethodByName(object, methodName2, 1, "Test");
    }

    public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        object.getClass().getDeclaredMethod(methodName).invoke(object);
    }

    public static void callMethodByName(Object object, String methodName, int i, String s) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        object.getClass().getDeclaredMethod(methodName, int.class, String.class).invoke(object, i, s);
    }

    void methodA() {
        System.out.println("Method A");
    }

    void methodB(int i, String s) {
        System.out.println("Method B: "+"\n\tParam1 - "+i+"\n\tParam 2 - "+s);
    }
}
输出:

索引速度更快 您可以使用FunctionInterface将方法保存在容器中以对其进行索引。您可以使用数组容器通过数字调用它们,或者使用hashmap通过字符串调用它们。通过这个技巧,您可以索引您的方法以更快地动态调用它们

Lambda语法 您还可以使用lambda语法:

public class ShapeArea {
    private final static double PI = 3.14;

    private Method[] methods = {
        number -> {
            return number * number;
        },
        number -> {
            return PI * number * number;
        },
    };

    public double run(int methodIndex, int number) {
        return methods[methodIndex].execute(number);
    }
}
这仅仅是:

on(obj).call(methodName /*params*/).get()
下面是一个更详细的例子:

public class TestClass {

    public int add(int a, int b) { return a + b; }
    private int mul(int a, int b) { return a * b; }
    static int sub(int a, int b) { return a - b; }

}

import static org.joor.Reflect.*;

public class JoorTest {

    public static void main(String[] args) {
        int add = on(new TestClass()).call("add", 1, 2).get(); // public
        int mul = on(new TestClass()).call("mul", 3, 4).get(); // private
        int sub = on(TestClass.class).call("sub", 6, 5).get(); // static
        System.out.println(add + ", " + mul + ", " + sub);
    }
}
这张照片是:

3,12,1


对于从非静态方法调用同一类中的方法的人,请参见以下代码:

class Person {
    public void method1() {
        try {
            Method m2 = this.getClass().getDeclaredMethod("method2");
            m1.invoke(this);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public void method2() {
        // Do something
    }

}

酷,我认为你使用getDeclaredMethod是对的,它可能比getMethod“更安全”。错了。是的,getDeclaredMethod确实适用于私有和受保护的方法。但是:它不适用于超类继承方法中定义的方法。所以,这在很大程度上取决于你想做什么。在许多情况下,您希望它能够工作,而不考虑定义方法的确切类。我应该将类文件放在哪里?最好解释一下EclipseIDE@Mr.Hyde如果我调用的方法根本不接受任何参数,我应该在和method.invoke中放置什么?似乎我还需要提供第二个参数,它应该是某个空的对象数组吗?如果在编译时已经知道该实例,为什么不直接执行className.getName.toString呢?你错过了思考的全部要点。就像我说的,在这种情况下没有必要,但是

t假设你总是知道这个实例是一个坏的编程习惯。@smaine:我建议删除这篇文章。在这种情况下,坏编程更像是一种赞美+1,因为唯一的答案承认OP在他的问题中没有指定参数,因为这也是我要找的。无论是使用还是使用都有点不高兴Java使用类型擦除,但知道它至少有反射,这一事实再次让我振奋起来:D现在Java 8中的lambdas语言真的在跟上现代开发的速度。现在唯一缺少的是对getter和setter的本地支持,或者C中已知的属性。这不是一个公平的1。Henrik可能并不提倡挤压异常,也没有为它们写任何东西,因为他只是试图展示反射。另外一个是展示一些潜在的异常。如果我写了这个,它会是。。。卡奇{…我得到的变量可能尚未为method.invokeobj,arg1,arg2,…;中的方法初始化。method=null;解决了这个问题,但在答案中提到它并不是一个坏主意。@DeaMon1 Java方法不使用退出代码,但如果该方法返回任何东西,invoke将返回它返回的任何东西。如果运行method时出现异常,invoke将返回它返回的任何东西od,异常将被包装在InvocationTargetException中。我不同意。编写这样的代码以确保安全非常容易,我已经用多种语言编写了这样的代码。例如,可以创建一组允许的方法,并且只允许在名称在集合中的情况下调用方法。更安全但更简单的方法是limiting将每个允许的方法设置为特定状态,并且不允许调用该方法,除非线程/接口/用户/任何符合此类标准的对象。对于此类问题,请不要对调用进行分类。现在,我正在创建一个简单的程序,允许用户使用web界面在任意对象上定义任意任务。我知道这确实是不安全的,但一旦收到配置,就会执行适当的测试,它允许非程序员轻松地配置任务,并使程序能够将自定义类链接到我使用反射的部分的通用代码,以便允许它们通过web界面配置要使用的方法,而无需更新GUI.这里的最佳答案。完整而简洁。正确的最佳答案。你从哪里获得方法对象?从reflect pkg。到未来的读者;如果你关心性能,你会想在任何时候都使用invokeExact。为此,调用站点签名必须与方法句柄类型完全匹配。通常需要一些小修补才能开始工作。在本例中,您需要使用:methodHandle=methodHandle.asTypemethodHandle.type.changeParameterType0,Object.class;强制转换第一个参数,然后像String result=String methodHandle.invokeExactobj;Object这样调用,对象应该至少有个值。这对于我所需要的非常有效。我有一个已经实例化了nd只需要从中获取一个方法。在这里为异常添加捕获是一个好主意,但在其他方面,这对我来说非常有效。我认为我避免null异常的方法是使用nullables,但我使用的方法名称范围非常有限,实际上只是一个从1到4的计数器。这不是Java中比较字符串的方式。你可以st使用.equals方法。否则,您只是比较它们是否是相同的对象引用,而实际上您并不关心对象引用-只是字符串内容是否匹配。您也可以通过反射按名称获取方法,因此不确定为什么要滚动自己的方法?如果someVariable确实是对象,请调用someVariable.getClass。此外,不能使用类作为唯一参数调用getMethod。也不能使用方法调用方法。正确:someVariable.getClass.getMethodcoolMethod,ParameterClass.invokearguments;这种技术似乎比反射好得多。它真的好得多吗?@DimitriKopriwa索引是使用ram而不是CPU计算的方法。例如:整数索引,算法的难度是O1。这应该是答案。非常干净的解决方案。我需要从json配置文件中读取方法名称。因此使用此技术,我可能只使用HashMap而不是反射。
Method method = someVariable.class.getMethod(SomeClass);
String status = (String) method.invoke(method);
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]
class Student{
    int rollno;
    String name;

    void m1(int x,int y){
        System.out.println("add is" +(x+y));
    }

    private void m3(String name){
        this.name=name;
        System.out.println("danger yappa:"+name);
    }
    void m4(){
        System.out.println("This is m4");
    }
}
import java.lang.reflect.Method;
public class StudentTest{

     public static void main(String[] args){

        try{

            Class cls=Student.class;

            Student s=(Student)cls.newInstance();


            String x="kichha";
            Method mm3=cls.getDeclaredMethod("m3",String.class);
            mm3.setAccessible(true);
            mm3.invoke(s,x);

            Method mm1=cls.getDeclaredMethod("m1",int.class,int.class);
            mm1.invoke(s,10,20);

        }
        catch(Exception e){
            e.printStackTrace();
        }
     }
}
public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
    object.getClass().getDeclaredMethod(methodName).invoke(object);
}
    public static void callMethodByName(Object object, String methodName, int i, String s) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        object.getClass().getDeclaredMethod(methodName, int.class, String.class).invoke(object, i, s);
    }
package practice;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

public class MethodInvoke {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
        String methodName1 = "methodA";
        String methodName2 = "methodB";
        MethodInvoke object = new MethodInvoke();
        callMethodByName(object, methodName1);
        callMethodByName(object, methodName2, 1, "Test");
    }

    public static void callMethodByName(Object object, String methodName) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        object.getClass().getDeclaredMethod(methodName).invoke(object);
    }

    public static void callMethodByName(Object object, String methodName, int i, String s) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
        object.getClass().getDeclaredMethod(methodName, int.class, String.class).invoke(object, i, s);
    }

    void methodA() {
        System.out.println("Method A");
    }

    void methodB(int i, String s) {
        System.out.println("Method B: "+"\n\tParam1 - "+i+"\n\tParam 2 - "+s);
    }
}
Method A Method B: Param1 - 1 Param 2 - Test
@FunctionalInterface
public interface Method {
    double execute(int number);
}

public class ShapeArea {
    private final static double PI = 3.14;

    private Method[] methods = {
        this::square,
        this::circle
    };

    private double square(int number) {
        return number * number;
    }

    private double circle(int number) {
        return PI * number * number;
    }

    public double run(int methodIndex, int number) {
        return methods[methodIndex].execute(number);
    }
}
public class ShapeArea {
    private final static double PI = 3.14;

    private Method[] methods = {
        number -> {
            return number * number;
        },
        number -> {
            return PI * number * number;
        },
    };

    public double run(int methodIndex, int number) {
        return methods[methodIndex].execute(number);
    }
}
on(obj).call(methodName /*params*/).get()
public class TestClass {

    public int add(int a, int b) { return a + b; }
    private int mul(int a, int b) { return a * b; }
    static int sub(int a, int b) { return a - b; }

}

import static org.joor.Reflect.*;

public class JoorTest {

    public static void main(String[] args) {
        int add = on(new TestClass()).call("add", 1, 2).get(); // public
        int mul = on(new TestClass()).call("mul", 3, 4).get(); // private
        int sub = on(TestClass.class).call("sub", 6, 5).get(); // static
        System.out.println(add + ", " + mul + ", " + sub);
    }
}
class Person {
    public void method1() {
        try {
            Method m2 = this.getClass().getDeclaredMethod("method2");
            m1.invoke(this);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public void method2() {
        // Do something
    }

}