代码之家  ›  专栏  ›  技术社区  ›  brasskazoo

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

  •  614
  • brasskazoo  · 技术社区  · 17 年前

    如果我有两个变量:

    Object obj;
    String methodName = "getName";
    

    不知道他们的级别 obj ,如何调用由标识的方法 methodName 在上面?

    正在调用的方法没有参数,并且 String 返回值。它是 javabean的getter .

    18 回复  |  直到 13 年前
        1
  •  1038
  •   Andrew    9 年前

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

    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

        2
  •  215
  •   Neuron MonoThreaded    8 年前

    使用 method invocation 反思:

    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[] 并声明要传递给方法的参数
        3
  •  119
  •   k_rollo    10 年前

    对于那些想要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();
    

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

    建议如下: Creating New Class Instances

        4
  •  56
  •   Petr Macek    17 年前

    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);
        }
    
    
    
    }
    
        5
  •  17
  •   Tom Hawtin - tackline    11 年前

    首先,不要。避免这种代码。它往往是非常糟糕的代码和不安全的(见第6节) Secure Coding Guidelines for the Java Programming Language, version 2.0 ).

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

        6
  •  14
  •   VonC    17 年前

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

    • 静态调用或实例调用(在一种情况下,您不需要类的实例,在另一种情况下,您可能需要依赖 现有默认构造函数 (可能在那里,也可能不在那里)
    • 公共或非公共方法调用(对于后者, 您需要在doPrivileged块内的方法上调用setAccessible findbugs won't be happy )
    • 如果您想抛出大量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;
    }
    
        7
  •  12
  •   chickeninabiscuit    17 年前
    Object obj;
    
    Method method = obj.getClass().getMethod("methodName", null);
    
    method.invoke(obj, null);
    
        8
  •  12
  •   anujin    13 年前
    //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");
    
        9
  •  11
  •   Amir Forsati    6 年前

    索引(更快)

    你可以用 FunctionalInterface 更快 .

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

    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);
        }
    }
    
        10
  •  9
  •   Christian Ullenboom    9 年前

    如果多次调用,则可以使用Java7中引入的新方法句柄。下面是返回字符串的方法:

    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]
    
        11
  •  8
  •   zxcv    17 年前

    这听起来像是Java反射包可以实现的。

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

    按名称调用方法:

    导入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);
         }
      }
    }
    
        12
  •  8
  •   Sandeep Nalla    7 年前

    以下是可随时使用的方法:

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

    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
        13
  •  7
  •   Marcel    5 年前
    try {
        YourClass yourClass = new YourClass();
        Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
        method.invoke(yourClass, parameter);
    } catch (Exception e) {
        e.printStackTrace();
    }
    
        14
  •  6
  •   Neuron MonoThreaded    8 年前
    Method method = someVariable.class.getMethod(SomeClass);
    String status = (String) method.invoke(method);
    

    SomeClass 是班级和学校吗 someVariable 是一个变量。

        15
  •  6
  •   Rahul Karankal    8 年前

    请参考以下代码,可能会对您有所帮助。

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

    谢谢

        16
  •  3
  •   Neuron MonoThreaded    8 年前

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

    StudentTest.java

    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();
            }
         }
    }
    
        17
  •  2
  •   nurnachman    11 年前

    您应该使用reflection-init初始化一个类对象,然后在此类中使用一个方法,然后使用 可选择的 试一试

    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);
    
        18
  •  2
  •   dina    9 年前

    使用 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);
    
        19
  •  1
  •   Luke H Gautam    10 年前

    这对我来说很好:

    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)来调用该方法。

        20
  •  1
  •   chrizonline    5 年前

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

    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
        }
    
    }
    
        21
  •  1
  •   FriskySaga    4 年前

    假设您正在从同一类中的静态方法调用静态方法。为此,可以对以下代码进行示例。

    class MainClass
    {
      public static int foo()
      {
        return 123;
      }
    
      public static void main(String[] args)
      {
        Method method = MainClass.class.getMethod("foo");
        int result = (int) method.invoke(null); // answer evaluates to 123
      }
    }
    

    为了解释,因为我们不希望在这里执行真正的面向对象编程,从而避免创建不必要的对象,所以我们将利用 class 要调用的属性 getMethod() .

    那我们就进去 null invoke() 方法,因为我们没有要对其执行此操作的对象。

    我们显式地强制转换 调用() 调用一个整数。

    现在您可能会想:“用Java进行所有这些非面向对象编程有什么意义?”

        22
  •  0
  •   Andronicus    6 年前

    具有 jooR

    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

        23
  •  -10
  •   László Papp    12 年前

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

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