首页 文章

将方法名称作为字符串给出时,如何调用Java方法?

提问于
浏览
606

如果我有两个变量:

Object obj;
String methodName = "getName";

在不知道 obj 类的情况下,如何调用 methodName 标识的方法呢?

被调用的方法没有参数,并且 String 返回值 . 它是Java bean的getter .

18 回答

  • 3

    这对我来说很好:

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

  • 10

    对于那些想要在Java 7中使用直接代码示例的人:

    Dog class:

    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 class:

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

    Output: 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, ...);
    

    Suggested reading: Creating New Class Instances

  • 52

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

    如果你必须这样做,那就更喜欢java.beans来反思 . beans 包裹反射允许相对安全和传统的访问 .

  • -9
    Method method = someVariable.class.getMethod(SomeClass);
    String status = (String) method.invoke(method);
    

    SomeClass 是类, someVariable 是变量 .

  • 72
    //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");
    
  • 6
    Object obj;
    
    Method method = obj.getClass().getMethod("methodName", null);
    
    method.invoke(obj, null);
    
  • 9

    从反射中使用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[] ,并声明要传递给方法的参数

  • 1

    请参考以下代码可能对您有所帮助 .

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

    谢谢....

  • 169

    我是这样做的:

    try {
        YourClass yourClass = new YourClass();
        Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
        method.invoke(yourClass, parameter);
    } catch (Exception e) {
        e.printStackTrace();
    }
    
  • 4

    从臀部编码,它将是这样的:

    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

  • 4

    这听起来像是Java Reflection包可以实现的 .

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

    特别是 Invoking Methods by Name:

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

    如果多次执行调用,则可以使用Java 7中引入的新方法句柄 . 这里我们为您的方法返回一个String:

    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]
    
  • 872

    您应该使用反射 - 初始化类对象,然后使用此类中的方法,然后在具有可选参数的对象上调用此方法 . 请记住将以下代码段包装在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);
    
  • 4

    Student.java

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

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

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

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

    • 静态或实例调用(在一种情况下,您不需要该类的实例,在另一种情况下,您可能需要依赖 existing default constructor ,可能存在也可能不存在)

    • 公共或非公共方法调用(对于后者, you need to call setAccessible on the method within an doPrivileged block ,其他findbugs won't be happy
      如果要抛弃大量的java系统异常(因此下面的代码中的CCException),

    • 封装成一个更易于管理的应用程序异常

    这是一个旧的java1.4代码,它考虑了这些点:

    /**
     * Allow for instance call, avoiding certain class circular dependencies. 
    * 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; }
  • 1

    使用 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);
    
  • 6

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

相关问题