Java リフレクションの Method オブジェクトからのメソッド呼び出し

これまでにリフレクション を用いて、実行時にクラスの情報、 オブジェクトの情報を取得する方法、及び、オブジェクトの作成方法について説明しました。

ここではメソッド名を文字列で指定して「Method オブジェクト」を取得して、そのメソッドを呼び出す方法をみてみましょう。

リフレクションで Method オブジェクトを取得してメソッドを呼ぶ

これまでに、クラス名を文字列で指定して Class オブジェクトを取得して、そこからコンストラクタオブジェクトを取得して、オブジェクトを生成する方法などをみてきました。

Class オブジェクトからのインスタンスの作成」でコンストラクタオブジェクトを取得する方法を説明しています。

Class オブジェクトを使うと、コンストラクタ・オブジェクトを生成できるだけでなく、メソッド・オブジェクトも生成することができます。

このとき、メソッド名は文字列で指定できます。

例えば、「Class オブジェクトからのインスタンスの作成」で使ったサンプルコードでは、 Employee というクラスの Class オブジェクトを取得して、 それを通して newInstance() メソッドを呼ぶことで Employee オブジェクトを作りました。

オブジェクトは Employee クラスにキャストして、 getLastName() メソッドを呼びました。 しかし今回は、newInstance() で作ったオブジェクトを Employee クラスにキャストしません。

Class オブジェクトの getMethod() メソッドを使って、getLastName() メソッドの Method オブジェクトを取得します。

Method オブジェクトは、 invoke() メソッドを持っており、 invoke() メソッドに対象となるオブジェクトを渡すことで、 そのオブジェクトのメソッドを呼び出ぶことができます。

Method オブジェクトでメソッドを呼び出す (引数なし)

Class オブジェクトの getMethod() オブジェクトを使って、Method オブジェクトを取得します。

package com.keicode.java.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestApp {

  public static void main(String[] args) {
    try {

      Class<?> c = null;
      c = Class.forName("com.keicode.java.test.Employee");
      Constructor constructor = c.getDeclaredConstructor(String.class, String.class);
      Object obj = constructor.newInstance("Ichiro", "Suzuki");
      Method method = c.getMethod("getLastName");
      String s = (String) method.invoke(obj);
      System.out.println("Last name: " + s);

    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (NoSuchMethodException e) {
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      e.printStackTrace();
    }
  }
}

このコードの 16行目で Method オブジェクトを取得して、17行目で Method オブジェクトの invoke() メソッドを呼ぶことで、そのメソッドを呼び出しています。

Employee クラスは「オブジェクトに関連する Class オブジェクトの取得」で使ったものと同じです。

Method オブジェクトでメソッドを呼び出す (引数あり)

上の例では引数を取らないメソッドの Method オブジェクトを取得しました。

次に引数をとる場合を考えてみましょう。

まず、次のような簡単な MyMath クラスを用意します。呼び出すメソッドは、int 型の引数を二つ受け取り単純な足し算をして返す add() メソッドです。

package com.keicode.java.test;

public class MyMath {
  public int add(int m, int n) {
    return m + n;
  }
}

add()メソッドの Method オブジェクトを取得して呼び出す例は次のようになります。

package com.keicode.java.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestApp {
  public static void main(String[] args) {
    try {
      Class<?> c = null;
      c = Class.forName("com.keicode.java.test.MyMath");
      Constructor constructor = c.getConstructor();
      Object obj = constructor.newInstance();
      Method method = c.getMethod("add", int.class, int.class);
      int ans = (int) method.invoke(obj, 10, 5);
      System.out.println("Answer: " + ans);
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (NoSuchMethodException e) {
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      e.printStackTrace();
    }
  }
}

14-15行目で Method オブジェクトを取得して、呼び出しています。

getMethod() メソッドでは、メソッド名と引数の型を指定しています。

メソッド名は同じでも、引数の型が違うとメソッドが見つからず NoSuchMethodException が発生するので注意が必要です。

以上、Method オブジェクトを取得して、その invoke() メソッドを呼ぶ方法について説明しました。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Java 入門