【问题标题】:How to find the declaring method of a bridge method?如何找到桥接方法的声明方法?
【发布时间】:2016-06-28 06:59:14
【问题描述】:

假设我们有以下接口和实现:

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){...}
}

我需要的是给定 Matcher 实现的 matches(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 情况外,这是一个有效的实现,因为它无法检测覆盖的 matches(..) 方法并返回 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();
}

【问题讨论】:

  • 仅供参考:一个明显的解决方案是将getDeclaredAnnotations() 应用于该方法。但这在这种情况下不起作用,因为 @Override 注释在运行时不再可访问。
  • 也许Method.getDeclaringClass 会有所帮助?
  • @Seelenvirtuose Method.getDeclaringClass() 在CustomMatcher 的情况下不起作用,因为声明类是NumberMatcher 而不是接口Matcher

标签: java generics reflection type-parameter java-bridge-method


【解决方案1】:

只要可以编辑实现,就可以使用标记注解:

@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
}

这将为CustomMatcher 返回Integer.class

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 2013-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多