|
19 | 19 | import java.lang.reflect.Field; |
20 | 20 | import java.lang.reflect.Method; |
21 | 21 | import java.lang.reflect.Modifier; |
22 | | -import java.util.ArrayList; |
23 | | -import java.util.Iterator; |
24 | | -import java.util.List; |
| 22 | +import java.util.*; |
25 | 23 | import java.util.stream.Collectors; |
26 | 24 |
|
27 | 25 | public class Reflector{ |
@@ -58,17 +56,41 @@ private static boolean canAccess(Method m, Object target) { |
58 | 56 | } |
59 | 57 | } |
60 | 58 |
|
| 59 | +private static Collection<Class> interfaces(Class c) { |
| 60 | + Set<Class> interfaces = new HashSet<Class>(); |
| 61 | + Deque<Class> toWalk = new ArrayDeque<Class>(); |
| 62 | + toWalk.addAll(Arrays.asList(c.getInterfaces())); |
| 63 | + Class iface = toWalk.poll(); |
| 64 | + while (iface != null) { |
| 65 | + interfaces.add(iface); |
| 66 | + toWalk.addAll(Arrays.asList(iface.getInterfaces())); |
| 67 | + iface = toWalk.poll(); |
| 68 | + } |
| 69 | + return interfaces; |
| 70 | +} |
| 71 | + |
| 72 | +private static Method tryFindMethod(Class c, Method m) { |
| 73 | + if(c == null) return null; |
| 74 | + try { |
| 75 | + return c.getMethod(m.getName(), m.getParameterTypes()); |
| 76 | + } catch(NoSuchMethodException e) { |
| 77 | + return null; |
| 78 | + } |
| 79 | +} |
| 80 | + |
61 | 81 | private static Method toAccessibleSuperMethod(Method m, Object target) { |
62 | 82 | Method selected = m; |
63 | | - while(selected != null && !canAccess(selected, target)) { |
64 | | - Class<?> s = selected.getDeclaringClass().getSuperclass(); |
65 | | - try { |
66 | | - selected = s.getMethod(m.getName(), m.getParameterTypes()); |
67 | | - } catch(NoSuchMethodException e) { |
68 | | - // ignore |
69 | | - } |
| 83 | + while(selected != null) { |
| 84 | + if(canAccess(selected, target)) return selected; |
| 85 | + selected = tryFindMethod(selected.getDeclaringClass().getSuperclass(), m); |
70 | 86 | } |
71 | | - return selected; |
| 87 | + |
| 88 | + Collection<Class> interfaces = interfaces(m.getDeclaringClass()); |
| 89 | + for(Class c : interfaces) { |
| 90 | + selected = tryFindMethod(c, m); |
| 91 | + if(selected != null) return selected; |
| 92 | + } |
| 93 | + return null; |
72 | 94 | } |
73 | 95 |
|
74 | 96 | public static Object invokeInstanceMethod(Object target, String methodName, Object[] args) { |
|
0 commit comments