LoginSignup
0
3

More than 5 years have passed since last update.

【Java】オブジェクトの private メソッドをクラス外から実行するラッパー

Last updated at Posted at 2018-07-03

【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);
    }
}
0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3