736

2 つの変数がある場合:

Object obj;
String methodName = "getName";

のクラスを知らずにobj、 で識別されるメソッドをどのように呼び出すことができmethodNameますか?

呼び出されるメソッドにはパラメーターがなく、String戻り値があります。Java Bean のゲッターです。

4

23 に答える 23

1043

腰からコーディングすると、次のようになります。

java.lang.reflect.Method method;
try {
  method = obj.getClass().getMethod(methodName, param1.class, param2.class, ..);
} catch (SecurityException e) { ... }
  catch (NoSuchMethodException e) { ... }

パラメーターは、必要な非常に具体的なメソッドを識別します (複数のオーバーロードが利用可能な場合、メソッドに引数がない場合は、 Give のみを指定しますmethodName)。

次に、呼び出してそのメソッドを呼び出します

try {
  method.invoke(obj, arg1, arg2,...);
} catch (IllegalArgumentException e) { ... }
  catch (IllegalAccessException e) { ... }
  catch (InvocationTargetException e) { ... }

繰り返しますが、引数.invokeがない場合は省略してください。しかし、ええ。Java リフレクションについて読む

于 2008-10-02T05:30:02.057 に答える
217

リフレクションからのメソッド呼び出しを使用します。

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

どこ:

  • "class name"クラスの名前です
  • objectToInvokeOnObject 型で、メソッドを呼び出すオブジェクトです。
  • "method name"呼び出したいメソッドの名前です
  • parameterTypesタイプClass[]であり、メソッドが受け取るパラメーターを宣言します
  • paramsタイプObject[]であり、メソッドに渡されるパラメーターを宣言します
于 2008-10-02T05:21:20.093 に答える
56

メソッドはこのように呼び出すことができます。他にも可能性があります (リフレクション 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);
    }



}
于 2008-10-02T05:33:31.657 に答える
17

まず、しないでください。この種のコードは避けてください。これは本当に悪いコードであり、安全でもない傾向があります(Javaプログラミング言語のセキュアコーディングガイドラインバージョン2.0のセクション6を参照)。

実行する必要がある場合は、リフレクションよりもjava.beansを使用してください。Beansはリフレクションをラップし、比較的安全で従来のアクセスを可能にします。

于 2008-10-02T14:08:40.903 に答える
14

同僚の回答を完成させるために、次のことに細心の注意を払う必要があります。

  • 静的呼び出しまたはインスタンス呼び出し (クラスのインスタンスが不要な場合もあれば、存在する場合も存在しない場合もある既存のデフォルト コンストラクターに依存する必要がある場合もあります)
  • 公開または非公開のメソッド呼び出し (後者の場合、doPrivileged ブロック内のメソッドで setAccessible を呼び出す必要があります。他のfindbugs は満足しません)
  • 多数の Java システム例外をスローバックする場合は、さらに 1 つの管理可能なアプリケーション例外にカプセル化します (したがって、以下のコードの 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;
}
于 2008-10-02T05:51:12.597 に答える
12
Object obj;

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

method.invoke(obj, null);
于 2008-10-02T05:22:24.803 に答える
8
try {
    YourClass yourClass = new YourClass();
    Method method = YourClass.class.getMethod("yourMethodName", ParameterOfThisMethod.class);
    method.invoke(yourClass, parameter);
} catch (Exception e) {
    e.printStackTrace();
}
于 2016-09-20T19:02:19.810 に答える
8

これは、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);
     }
  }
}
于 2008-10-02T05:22:24.023 に答える
6

次のコードを参照してください。

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

ありがとう....

于 2016-05-20T06:31:23.417 に答える
6
Method method = someVariable.class.getMethod(SomeClass);
String status = (String) method.invoke(method);

SomeClassはクラスでsomeVariable、変数です。

于 2016-12-27T05:10:10.227 に答える
2

使用して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);
于 2016-11-23T07:32:23.247 に答える
1

これは私にとってはうまくいきます:

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

その名前を別のメソッド (メインなど) に渡すことで、メソッドを呼び出すことができます。

于 2015-10-09T18:29:01.543 に答える
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
    }

}
于 2021-01-25T02:08:36.110 に答える
0

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

于 2020-02-02T13:17:12.630 に答える
-9

私にとって、非常に単純でばかげた方法は、次のようにメソッド呼び出し元メソッドを単純に作成することです。

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()); 
于 2010-06-16T20:21:32.963 に答える