Fla*_*vio 6 java generics reflection overriding
我有以下代码,通用ITest接口由非通用ITestDouble接口扩展.该op方法被覆盖ITestDouble.
当我尝试列出所有方法时ITestDouble,我得到op两次.如何验证它们实际上是相同的方法?
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();
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
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)
Run Code Online (Sandbox Code Playgroud)
PS我知道这是与重写方法上的Java Class.getMethods()行为相同的问题,但这个问题没有得到真正的答案:isBridge()调用总是返回false.
编辑:我也很好,任何库都可以为我过滤掉"重复" op方法.
遗憾的是,你不能拥有这些信息,因为就JVM而言,它ITestDouble有一个op(Number)完全独立的合法方法op(Double).它实际上是您的Java 编译器,可确保方法始终重合.
这意味着,你可以创建的病理实现ITestDouble与完全不同的实现op(Number),并op(Double)通过使用JDK5预编译或动态代理:
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
}
Run Code Online (Sandbox Code Playgroud)
编辑: 刚刚学习了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();
Run Code Online (Sandbox Code Playgroud)
现在,如果你迭代,methods你会看到以下内容:
void other();
int op(java.lang.Double);
int op(java.lang.Double);
Run Code Online (Sandbox Code Playgroud)
现在可以轻松过滤重复项:
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;
}
Run Code Online (Sandbox Code Playgroud)