publicメソッドの呼び出し

前回のprivateメソッドの呼び出しのついでに、publicメソッドについて、メモ。

publicメソッドを外部からリフレクトで呼び出すなら、普通は「org.apache.commons.beanutils.MethodUtils」を使うことになるでしょう。

で、以下の2つのメソッドの違い

  • MethodUtils#invokeMethod
  • MethodUtils#invokeExactMethod


こんなクラスがあったとして。

public class A {
    public String b(String name) {
        return name + "さん、こんにちは。";
    }
}


こんなんで実行すると。(クラスAとクラスTestAは同じパッケージ)

import org.apache.commons.beanutils.MethodUtils;
public class TestA {

    public static void main(String[] args) {
        try {
            System.out.println(MethodUtils.invokeMethod(new A(), "b", "マイケル"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            System.out.println(MethodUtils.invokeExactMethod(new A(), "b", "マイケル"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


こんな出力結果になる。(invokeMethodもinvokeExactMethodも同じ)

マイケルさん、こんにちは。
マイケルさん、こんにちは。

Aクラスのアクセスをpublicからdefaultにすると。(public class A → class A)

class A {
    public String b(String name) {
        return name + "さん、こんにちは。";
    }
}


こんな出力結果になる。(invokeMethodは成功、invokeExactMethodはダメ)

マイケルさん、こんにちは。
java.lang.NoSuchMethodException: No such accessible method: b() on object: A
	at org.apache.commons.beanutils.MethodUtils.invokeExactMethod(MethodUtils.java:332)
	at org.apache.commons.beanutils.MethodUtils.invokeExactMethod(MethodUtils.java:286)
	at org.apache.commons.beanutils.MethodUtils.invokeExactMethod(MethodUtils.java:248)
	at TestA.main(TestA.java:11)

bメソッドのアクセスをpublicからdefaultにすると。(public String b → String b)

class A {
    String b(String name) {
        return name + "さん、こんにちは。";
    }
}


こんな出力結果になる。(invokeMethodもinvokeExactMethodもダメ)

java.lang.NoSuchMethodException: No such accessible method: b() on object: A
	at org.apache.commons.beanutils.MethodUtils.invokeMethod(MethodUtils.java:214)
	at org.apache.commons.beanutils.MethodUtils.invokeMethod(MethodUtils.java:162)
	at org.apache.commons.beanutils.MethodUtils.invokeMethod(MethodUtils.java:114)
	at TestA.main(TestA.java:6)
java.lang.NoSuchMethodException: No such accessible method: b() on object: A
	at org.apache.commons.beanutils.MethodUtils.invokeExactMethod(MethodUtils.java:332)
	at org.apache.commons.beanutils.MethodUtils.invokeExactMethod(MethodUtils.java:286)
	at org.apache.commons.beanutils.MethodUtils.invokeExactMethod(MethodUtils.java:248)
	at TestA.main(TestA.java:11)


MethodUtils#invokeMethodのソースを見ると、内部でgetMatchingAccessibleMethodっていうメソッドを呼んでいて、クラスのアクセスを変更してました。invokeMethodとinvokeExactMethodの違いはそこだけのようです。

ということで、実行対象のメソッドを持っているクラスが、MethodUtilsクラスにとってアクセスできるかどうかの違いで使い分ける。

アクセス invokeMethod invokeExactMethod
MethodUtilsクラスにとってアクセスできるクラス
MethodUtilsクラスにとってアクセスできないクラス ×
MethodUtilsクラスにとってアクセスできないメソッド × ×

まー、結局、メソッド名短いし、invokeMethodを使ってりゃいいということです。