如何获取间接实现的通用接口的实际类型参数?

pol*_*nts 7 java generics reflection interface

我有一个参数化的界面,以多种不同的方式实现.在运行时,我需要弄清楚,给定一个实现该接口的任意对象,接口的实际类型参数是什么.

这是一个解释问题的片段,以及解决问题的中途尝试(也在ideone.com上):

import java.util.*;
import java.lang.reflect.*;

interface Awesome<X> { }
class Base<E> implements Awesome<Set<E>> { }
class Child extends Base<List<Integer>> { }

class AwesomeExample {      
    public static void main(String[] args) {
        Awesome<Set<List<Integer>>> x = new Child();

        System.out.println(
            ((ParameterizedType)
                Child.class.getGenericSuperclass()
            ).getActualTypeArguments()[0]
        );
        // prints "java.util.List<java.lang.Integer>"

        System.out.println(
            ((ParameterizedType)
                Base.class.getGenericInterfaces()[0]
            ).getActualTypeArguments()[0]
        );
        // prints "java.util.Set<E>"        

        investigate(x);
        // we want this to print "Set<List<Integer>>"
    }

    static void investigate(Awesome<?> somethingAwesome) {
        // how to do this?
    }
}
Run Code Online (Sandbox Code Playgroud)

看起来在运行时有足够的泛型类型信息来推断:

  • Child extends Base<List<Integer>>
  • Base<E> implements Awesome<Set<E>>

因此,我们可以把所有的点点滴滴放在一起得出结论:

  • Child implements Awesome<Set<List<Integer>>>

所以看起来这个问题是可以解决的,但并不是那么简单,因为我们必须使用任意的类/接口层次结构.这是唯一的方法吗?有更简单的方法吗?有人写过图书馆吗?

Ale*_*exR -1

最简洁的答案是不。我同意这是一个遗憾... :( 原因是 Java 在编译阶段删除了类型参数。它们不存在于字节代码中。它们仅由编译器使用。

要解决您的问题,您必须添加另一个 Class 类型的“常规”参数,并在创建 Base 实例时将其传递给构造函数:

class Base<E> implements Awesome<Set<E>> { 
    private E type;
    public Base(E type) {
        this.type = type;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 类型信息位于字节码中。所以你是不正确的。您可以在该位置获取类型信息。谷歌搜索超级类型令牌来获取示例。 (2认同)