我有以下代码,通用ITest接口由非通用ITestDouble接口扩展. ITestDouble会覆盖op方法.
当我尝试列出ITestDouble的所有方法时,我得到了两次操作.如何验证它们实际上是相同的方法?
public class Test { public static void main(String[] args) throws NoSuchMethodException { for (Method m : ITestDouble.class.getMethods()) { System.out.println(m.getDeclaringClass() + ": " + m + "(bridge: " + m.isBridge() + ")"); } } public interface ITestDouble extends ITest<Double> { @Override public int op(Double value); @Override public void other(); } public interface ITest<T extends Number> { public int op(T value); public void other(); } }
输出:
interface Test$ITestDouble: public abstract int Test$ITestDouble.op(java.lang.Double)(bridge: false) interface Test$ITestDouble: public abstract void Test$ITestDouble.other()(bridge: false) interface Test$ITest: public abstract int Test$ITest.op(java.lang.Number)(bridge: false)
PS我知道这是与Java Class.getMethods() behavior on overridden methods相同的问题,但这个问题没有得到真正的答案:isBridge()调用总是返回false.
编辑:
对于任何可以为我过滤掉“复制”操作方法的脏工作,我也很好.
解决方法
遗憾的是,您无法获得该信息,因为就JVM而言,ITestDouble有一个合法的方法op(Number),它可以完全独立于op(Double).它实际上是您的Java编译器,可确保方法始终重合.
这意味着您可以通过使用JDK5之前的编译器或动态代理,使用完全不同的op(Number)和op(Double)实现来创建ITestDouble的病态实现:
public static void main(String[] args) throws NoSuchMethodException { final Method opNumber = ITest.class.getMethod("op",Number.class); final Method opDouble = ITestDouble.class.getMethod("op",Double.class); final Method other = ITestDouble.class.getMethod("other"); ITestDouble dynamic = (ITestDouble) Proxy.newProxyInstance( ITestDouble.class.getClassLoader(),new Class<?>[]{ITestDouble.class},new InvocationHandler() { @Override public Object invoke(Object proxy,Method m,Object[] args) throws Throwable { if (opDouble.equals(m)) return 1; if (opNumber.equals(m)) return 2; // etc.... return null; } }); System.out.println("op(Double): " + dynamic.op(null); // prints 1. System.out.println("op(Number): " + ((ITest) dynamic).op(null); // prints 2. Compiler gives warning for raw types }
编辑:
刚刚学习了Java ClassMate.它是一个可以正确解析声明中所有类型变量的库.这是非常容易使用:
TypeResolver typeResolver = new TypeResolver(); MemberResolver memberResolver = new MemberResolver(typeResolver); ResolvedType type = typeResolver.resolve(ITestDouble.class); ResolvedTypeWithMembers members = memberResolver.resolve(type,null,null); ResolvedMethod[] methods = members.getMemberMethods();
void other(); int op(java.lang.Double); int op(java.lang.Double);
现在可以轻松过滤重复项:
public boolean canOverride(ResolvedMethod m1,ResolvedMethod m2) { if (!m1.getName().equals(m2.getName())) return false; int count = m1.getArgumentCount(); if (count != m2.getArgumentCount()) return false; for (int i = 0; i < count; i++) { if (!m1.getArgumentType(i).equals(m2.getArgumentType(i))) return false; } return true; }