假设我们有以下接口和实现:
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 :(得分: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.class
返回CustomMatcher
。
我认为没有办法在运行时检索此信息,因为Method
- 不知道它们来自何处。这可能是有意的,因为多个接口可以定义相同的方法签名。