如果有两个变量:

Object obj;
String methodName = "getName";

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

被调用的方法没有参数,只有一个String返回值。它是Java bean的getter。


当前回答

这听起来像是Java Reflection包可以做到的事情。

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

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

进口数组;*;

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中的参数,请省略。但是是的。阅读Java反射

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

SomeClass是类,somvariable是变量。

如果多次调用,则可以使用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]

这听起来像是Java Reflection包可以做到的事情。

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

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

进口数组;*;

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

索引(快)

您可以使用FunctionalInterface将方法保存在容器中以索引它们。您可以使用数组容器通过数字调用它们,或者使用hashmap通过字符串调用它们。通过这个技巧,可以为方法建立索引,从而更快地动态调用它们。

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

编辑2022

刚才我在想为你提供一个通用的解决方案,与所有可能的方法与变量数:

@FunctionalInterface
public interface Method {
    Object execute(Object ...args);
}

public class Methods {
    private Method[] methods = {
        this::square,
        this::rectangle
    };

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

    private double rectangle(int width, int height) {
        return width * height;
    }

    public Method run(int methodIndex) {
        return methods[methodIndex];
    }
}

用法:

methods.run(1).execute(width, height);