如何修剪使用Java反射获得的相同方法的变体?

时间:2017-02-24 22:53:26

标签: java reflection groovy

我正在使用反射发现满足某些条件的方法并调用找到的方法。

检查以下代码。使用Groovy ..

class TestClass<T>{
    T hello(){
        return null
    }
}

class TestSubClass extends TestClass<List<String>>{

    List<String> hello(){
        return null
    }
}

TestSubClass.methods.each{
    if(it.name.contains("hello")){
        println it.toGenericString()
    }
}

打印出来

public java.util.List<java.lang.String> TestSubClass.hello() // <-- most relevant method for a user of this class
public java.lang.Object TestSubClass.hello()
public java.lang.Object TestSubClass.super$2$hello()

Java反射基于继承/泛型返回相同方法的多个声明,这是可以理解的。

就我而言,我想发现具有最合适签名的方法,包括returnTypes的确切类型。例如,在上面的示例中,输出中的第一个方法具有完整签名,这是我们通常调用的方法(没有反射)。

注意:上面是一个简化的例子。真正的逻辑不是基于命名来寻找方法。

3 个答案:

答案 0 :(得分:1)

Java规范要求使用一种方法来标记合成,如果它没有在源代码中明确显示。

  

Java编译器发出的构造必须标记为合成if   它不对应于显式声明的构造或   隐含在源代码中,除非发出的构造是一个类   初始化方法(JVMS§2.9)。

JAVA specifications

您可以尝试:

TestSubClass.methods.each{
    if(it.name.contains("hello") && !m.isSynthetic()){
        println it
    }
}

您还可以检查该方法是否已桥接。这是一个类似的概念: https://stackoverflow.com/a/5007394/1754020

答案 1 :(得分:1)

编译器生成其他2种方法。幸运的是,您可以查看以下属性:synthetic

TestSubClass.declaredMethods.each{
    if(it.name.contains("hello") && !it.synthetic) {
        println it.toGenericString()
    }
}

现在只打印:

public java.util.List<java.lang.String> test.TestSubClass.hello()

答案 2 :(得分:0)

  

在我的情况下,我想以最合适的方式发现这种方法   签名,包括确切类型的退货类型。

如果它是您想知道的Java API,那么您将要查看课程public static <D extends DateSerial<?>> DateSerial.Config<D> obtainMetadata(Class<D> cls) { Method exe = Stream.of(cls.getDeclaredMethods()) .filter(m -> m.getParameterCount() == 0 && m.getReturnType() == DateSerial.Config.class) .filter(m -> { int mod = m.getModifiers(); return Modifier.isStatic(mod) && Modifier.isPublic(mod); }) .findFirst() .orElseThrow(() -> new IllegalArgumentException( "No metadata accessor for " + cls.getName())); : : } 。它包含大量允许您查询类型的反射方法。

例如,以下代码片段搜索在提供的类型上声明的所有方法,用于以下方法:不带参数,String[]和{{1}},并且返回类型为{{1 }} ...

{{1}}

您可以根据需要精确地进行审讯。例如,您可以根据具有一定数量参数的方法过滤方法,最后一个是{{1}}数组等等。警告经理:Java反射代码冗长,丑陋,并且可能很难读取。