Java 如何使用反射获取方法的泛型返回类型

Java 如何使用反射获取方法的泛型返回类型,java,reflection,Java,Reflection,有没有办法获得泛型方法的返回类型-返回类型 public interface MyGeneric<T> { T doSomething(); } public interface MyElement extends MyGeneric<Element> { } public class Main { public static final void main(String[] args) { System.out.println(MyElement.

有没有办法获得泛型方法的返回类型-返回类型

public interface MyGeneric<T> {
  T doSomething();
}

public interface MyElement extends MyGeneric<Element> {

}

public class Main {
  public static final void main(String[] args) {
    System.out.println(MyElement.class.getMethod("doSomething", new Class<?>[0]).magic()); // => Element
  }
}
公共接口MyGeneric{
T doSomething();
}
公共接口MyElement扩展了MyGeneric{
}
公共班机{
公共静态最终void main(字符串[]args){
System.out.println(MyElement.class.getMethod(“doSomething”,新类[0]).magic());//=>元素
}
}

我使用方法.getReturnType()获取java.lang.Object,而不使用。“魔法”方法存在吗?

不,魔法一般不存在。如果您想使用技巧获取该数据,可以在界面中要求该数据,如所述


另一方面,如果您的类型是特殊的(如列表),您可以这样做。请参阅以了解特殊类型。

不幸的是,核心Java库中的反射功能对于分析泛型类型来说相当差。您可以使用
getGeneric…
方法(例如,
getGenericReturnType()
),但它们的工作并不那么好,它们通常返回
Type
实例,而不是
Class
实例。我觉得这很难处理

我已经基于.NET编写了自己的反射API,我觉得它更加一致(特别是在泛型方面)。考虑以下输出:

import com.strobel.reflection.Type;

interface MyGeneric<T> {
    T doSomething();
}

interface Element {}

interface MyElement extends MyGeneric<Element> {}

class Main {
    public static final void main(String[] args) throws NoSuchMethodException {
        // prints "class java.lang.Object":
        System.out.println(
            MyElement.class.getMethod("doSomething").getReturnType()
        );
        // prints "T":
        System.out.println(
            MyElement.class.getMethod("doSomething").getGenericReturnType()
        );
        // prints "Element":
        System.out.println(
            Type.of(MyElement.class).getMethod("doSomething").getReturnType()
        );
    }
}
import com.strobel.reflection.Type;
接口MyGeneric{
T doSomething();
}
接口元素{}
接口MyElement扩展了MyGeneric{}
班长{
公共静态最终void main(字符串[]args)引发NoSuchMethodException{
//打印“class java.lang.Object”:
System.out.println(
MyElement.class.getMethod(“doSomething”).getReturnType()
);
//打印“T”:
System.out.println(
MyElement.class.getMethod(“doSomething”).getGenericReturnType()
);
//打印“元素”:
System.out.println(
Type.of(MyElement.class).getMethod(“doSomething”).getReturnType()
);
}
}

欢迎使用。实际上,我刚刚提交了一个bug修复程序,它阻止了这个示例的工作(它位于
开发
分支的顶端)。

可以在运行时检查这个问题:我假设
接口MyElement
应该是
接口MyElement扩展MyGeneric
?我也在想同样的事情。在MyElement上调用时,查找“doSomething”可能会导致NoSuchMethodException。抱歉,修复了(MyElement.class).getMethod(“doSomething”).getReturnType()的类型与我正在搜索的类似。你能告诉我你是如何实现它的(一般策略还是链接到你的源代码所在的类)?相关的代码分布在几个类中。将
java.lang.reflect
类型和成员转换为我的API使用的形式的代码位于
com.strobel.reflection.Resolver
中。所有类型的抽象类都是
com.strobel.reflection.Type
,从中可以找到它调用的类,以填充和缓存声明和继承成员的完整列表。反射框架的存储库根是。如果我有一个返回类型或参数为参数化类型的方法——例如,public void setMyIntMaybe(Option[Int]intMaybe)——那么内部类型将被擦除,在本例中显示为Option[Object]——与方法的返回类型或参数类型相同。Strobel的库很好,但没有克服这个限制。@SamerAdra不应该是这样。您使用的是Java以外的JVM语言吗?我没有用Scala、Kotlin或任何其他语言测试我的泛型反射支持。@MikeStrobel,我在用Scala。幸运的是,我能够组合一些适用于Scala 2.10.4+:(在方法“invokeScalater”中)的东西。如果您引用的是答案,则这些答案之所以有效,是因为它们正在检索字段声明中的类型。