考えてみてくださいとかいいつつ
コレ
result = HogeX.invoke(x, "methodName", param1, param2);
自分でてきとうに書いてみました。 Class.getDeclaredMethod() が微妙に使えない子だった(シグネチャが引数に完全一致するメソッドしか取ってこれない)。
一応実行時に型チェックしつつ、protectedメソッドにもちゃんとアクセスできます。プリミティブ型の扱いがぞんざいなのはしょうがない。Javaだし。
多重継承か mixin が欲しくなる感じのアレです。
import java.lang.reflect.Method; public class MethodSeek { public static Method getMethod(Object obj, String mname, Object... args) throws NoSuchMethodException { Class klass = obj.getClass(); Method[] methods = klass.getDeclaredMethods(); for (Method m : methods) { if (m.getName().equals(mname)) { if (typeCheck(m.getParameterTypes(), args)) { return m; } } } throw new NoSuchMethodException(klass.getName() + "." + mname + "()"); } protected static boolean typeCheck(Class[] types, Object[] args) { if (types.length != args.length) return false; for (int i = 0; i < types.length; i++) { if (!(types[i].isInstance(args[i]))) return false; } return true; } }
こんなかんじで HogeX を定義できます。
import java.lang.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; class Hoge { private int a; public Hoge(int a) { this.a = a; } protected Integer prot(Integer b, Integer c) { System.out.println("Hoge:protected"); return a + b + c; } } class HogeX extends Hoge { public HogeX(int a) { super(a); } public static <T> T invoke(Object obj, String mname, Object... args) throws IllegalAccessException, InvocationTargetException, NoSuchMethodException { Method m = MethodSeek.getMethod(obj, mname, args); return (T)(m.invoke(obj, args)); } } class Test1 { public static void main(String[] args) { try { Hoge x = new Hoge(100); Integer result = HogeX.invoke(x, "prot", 30, 4); System.out.println(result); result = HogeX.invoke(x, "prot", 1, 2, 3); System.out.println(result); } catch (Exception e) { e.printStackTrace(); } } }
実行結果
Hoge:protected 134 java.lang.NoSuchMethodException: Hoge.prot() at MethodSeek.getMethod(MethodSeek.java:14) at HogeX.invoke(test1.java:20) at Test1.main(test1.java:31)