2016-06-28 36 views
3

假设我们有以下的接口和实现:如何查找桥接方法的声明方法?

interface Matcher<T>{ 
    boolean matches(T arg); 
} 

class NumberMatcher<T extends Number> implements Matcher<T>{ 
    @Override 
    public boolean matches(T arg){...} 
} 

class StringMatcher extends Matcher<String>{ 
    @Override 
    public boolean matches(String arg){ ...} 
} 

class CustomMatcher extends NumberMatcher<Integer> { 
    public boolean matches(String arg){...} 

    @Override 
    public boolean matches(Integer arg){...} 
} 

我需要的是一个给定的匹配器实现的匹配(T)方法的参数的类型。

NumberMatcher numberMatcher = new NumberMatcher<Long>(); 
StringMatcher stringMatcher = new StringMatcher(); 
CustomMatcher customMatcher = new CustomMatcher(); 
Matcher<Date> dateMatcher = new Matcher<Date>(){...}; 

getArgumentType(numberMatcher) // should return Number.class 
getArgumentType(stringMatcher) // should return String.class 
getArgumentType(customMatcher) // should return Integer.class 
getArgumentType(dateMatcher) // should return Object.class 

这里是除了CustomMatcher箱子一个可行的实施方式中,导致它未能检测到被覆盖的匹配(..)方法并返回String.class代替Integer.class

Class<?> getArgumentType(Matcher<?> matcher) { 
    Method[] methods = matcher.getClass().getMethods(); 
    for (Method method : methods) { 
     if (isMatchesMethod(method)) { 
      return method.getParameterTypes()[0]; 
     } 

    } 
    throw new NoSuchMethodError("Method 'matches(T)' not found!"); 
} 

private boolean isMatchesMethod(Method method) { 
    if (!isPublic(method.getModifiers())) 
     return false; 

    if (method.getParameterCount() != 1) 
     return false; 

    return method.getName().equals("matches"); 
} 

编辑:

我要寻找的是需要指定参数类型这样一个解决方案:只要你可以编辑

interface Matcher<T>{ 
    boolean matches(T arg); 
    Class<T> argumentType(); 
} 
+0

仅供参考:显而易见的解决方案是将'getDeclaredAnnotations()'应用于该方法。但是这种情况在这种情况下不起作用,因为'@ Override'注释在运行时不再可用。 –

+0

也许['Method.getDeclaringClass'](https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#getDeclaringClass--)会有帮助吗? – Seelenvirtuose

+0

@Seelenvirtuose Method.getDeclaringClass()在'CustomMatcher'的情况下不起作用,因为声明类是'NumberMatcher'而不是'Matcher'接口 – Chriss

回答

0

在实现中,您可以使用标记注释:

@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.METHOD) 
public @interface ThisIsTheOne { 

} 

public class CustomMatcher extends NumberMatcher<Integer> { 

    @Override 
    @ThisIsTheOne 
    public boolean matches(Integer arg){ return true; } 

    public boolean matches(String arg){ return true; } 
} 

private static boolean isMatchesMethod(Method method) { 
    if (method.getAnnotation(ThisIsTheOne.class) != null) { 
     return true; 
    } 
    // do the same as before, so it works on non-annotated methods too 
} 

这将返回Integer.classCustomMatcher

我不认为有办法在运行时检索这些信息,因为Method-不知道它们来自哪里。这可能是故意的,因为多个接口可以定义相同的方法签名。