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

私は必要なもの与えられたのMatcherの実装の一致(T)メソッドのパラメータの型です。それがオーバーライドされたマッチ(..)メソッドを検出できないとString.classの代わりInteger.classを返す原因ここ

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の例を除いて働く実装です。

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"); 
} 

EDIT:限り、あなたが編集できるよう

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'の場合には動作しません。なぜなら、宣言クラスは' Matcher'ではなく、 'NumberMatcher'です。 – 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 
} 

CustomMatcherの場合はInteger.classが返されます。

Methodはどこから来たのかわからないので、実行時にこの情報を取得する方法はないと思います。複数のインタフェースが同じメソッドシグネチャを定義できるため、これは意図的なものです。

関連する問題