【Java】オブジェクトの private メソッドをクラス外から実行するラッパー
テストを書いているとオブジェクトのプライベートメソッドにアクセスすることもあるが、
毎回 reflection を直接叩いていてはやっていられないので簡単なラッパー関数を作った
class Main {
/**
* オブジェクトの private method を実行
*
* @param target 対象のオブジェクトのインスタンス
* @param name メソッド名
* @param <T> 対象オブジェクトの型
* @throws Exception メソッド実行時の例外
*/
public static <T> void invokeMethod(T target, String name) throws Exception {
final Method method = target.getClass().getDeclaredMethod(name);
method.setAccessible(true);
method.invoke(target);
}
/**
* オブジェクトの private method を実行
*
* @param target 対象のオブジェクトのインスタンス
* @param name メソッド名
* @param parameterValues 引数のリスト
* @param <T> 対象オブジェクトの型
* @throws Exception メソッド実行時の例外
*/
public static <T> void invokeMethod(T target, String name, List<?> parameterValues) throws Exception {
// 引数の型の配列を取得
final Class<?>[] parameterTypes = new Class[parameterValues.size()];
parameterValues.stream().map(Object::getClass).collect(Collectors.toList()).toArray(parameterTypes);
final Method method = target.getClass().getDeclaredMethod(name, parameterTypes);
method.setAccessible(true);
method.invoke(target, parameterValues.toArray());
}
/**
* オブジェクトの private method を実行
*
* @param target 対象のオブジェクトのインスタンス
* @param name メソッド名
* @param parameterValues 引数のリスト
* @param resultType 結果オブジェクトの Class インスタンス
* @param <T> 対象オブジェクトの型
* @param <U> 返り値の型
* @return メソッドの返り値
* @throws Exception メソッド実行時の例外
*/
public static <T, U> U invokeMethod(T target, String name, List<?> parameterValues, Class<U> resultType) throws Exception {
// 引数の型の配列を取得
final Class<?>[] parameterTypes = new Class[parameterValues.size()];
parameterValues.stream().map(Object::getClass).collect(Collectors.toList()).toArray(parameterTypes);
final Method method = target.getClass().getDeclaredMethod(name, parameterTypes);
method.setAccessible(true);
return resultType.cast(method.invoke(target, parameterValues.toArray()));
}
static class PrivateMethodTest {
private void sayHelloWorld() {
System.out.println(makeHelloMessage("world!"));
}
private void sayHello(String message) {
System.out.println(makeHelloMessage(message));
}
private String makeHelloMessage(String message) {
return "Hello, " + message;
}
}
public static void main(String[] args) throws Exception {
final PrivateMethodTest target = new PrivateMethodTest();
invokeMethod(target, "sayHelloWorld");
final List<Object> params = new ArrayList<>();
params.add("world!");
invokeMethod(target, "sayHello", params);
final String message = invokeMethod(target, "makeHelloMessage", params, String.class);
System.out.println(message);
}
}