java - 是否有更简单的方法来检索子类实现中的硬编码类型参数?

标签 java generics reflection

给定以下界面:

public interface GenericInterface<T> {

    T getValue();
    void setValue(T newVal);
}

以及以下实现:

public class FixedImpl implements GenericInterface<String> {

    String value;

    public FixedImpl(String value) {
        this.value = value;
    }

    @Override
    public String getValue() {
        return value;
    }

    @Override
    public void setValue(String newVal) {
        value = newVal;
    }
}

我希望能够确定 FixedImpl 的情况, String.classGenericInterface.T 的值通过询问FixedImpl.class .

我目前的想法:

  1. GenericInterface 中查找方法名称返回 <T> - 在本例中,有 "getValue" .
  2. 遍历 FixedImpl.class 中声明的所有方法具有相同的名称,并收集所有不同的返回类型。
  3. 距离 Object 最远的返回类型我的值是GenericInterface.T .

但是这个过程存在一些问题:

  • 它仅适用于包含返回 <T> 的方法的泛型类型。您不能使用 setValue(T) 安全地执行相同的操作。 ,因为在 Java 源代码中可以通过参数/数量进行方法重载。它仅适用于 T getValue()因为返回值重载不是(除非我弄错了)。
  • 它可能与 Java 8 默认方法或(仍然通用)可能抽象父类(super class)中的通用方法实现有奇怪的交互。
  • 这有点困惑。

有人能给我指出一种更简单/更可靠的方法来获取相同的信息吗?我似乎找不到,但我想我应该问问那些高人一等的人:)

注意:如果您想知道为什么我需要这个,那是因为我想以编程方式构造具有类似硬编码类型参数的容器类的模拟,但 POJO 值而不是简单的字符串。

编辑:我最终找到了以下解决方案(在看到@stony-zhang 之前):

public static <G> List<Class> getConcreteTypes(Class<? extends G> implClass, Class<G> genericClass) {

    List<Class> concreteTypes = new ArrayList<Class>();

    for (Type type : implClass.getGenericInterfaces()) {

        if (!(type instanceof ParameterizedTypeImpl)) continue;

        ParameterizedTypeImpl parameterizedType = (ParameterizedTypeImpl) type;

        if (parameterizedType.getRawType() != genericClass) continue;

        for (Object arg : parameterizedType.getActualTypeArguments()) {
            if (!(arg instanceof Class))
                throw new IllegalArgumentException("Class " + implClass + " not concrete for generic type " + genericClass);
            concreteTypes.add((Class) arg);
        }
    }

    return concreteTypes;
}

最佳答案

可以通过以下方式获取T的类,在接口(interface)中添加一个方法getMessageClass(),并在FixedImpl中添加实现的方法,

    @SuppressWarnings("rawtypes")
public Class getMessageClass() {
            int index =0; //In the case, you only have a generic type, so index is 0 to get the first one.
    Type genType = getClass().getGenericSuperclass();
    if (!(genType instanceof ParameterizedType)) {
        return Object.class;
    }
    Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
    if (index >= params.length || index < 0) {
        throw new RuntimeException("Index outof bounds");
    }
    if (!(params[index] instanceof Class)) {
        return Object.class;
    }
    return (Class) params[index];
}

在您的情况下,如果您有多个子类,要使用它,请创建一个抽象类来实现 GenericInterface 接口(interface),然后所有子类都从新的抽象类扩展,

public class abstract abstractImpl<T> implements implements GenericInterface<T> {
        @SuppressWarnings("rawtypes")

    @Override
      public Class getMessageClass() {
           ...............
      }
}

关于java - 是否有更简单的方法来检索子类实现中的硬编码类型参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16726167/

相关文章:

java - Java “Foo f = new Foo() ”中的对象初始化是否与在C中将malloc用作指针相同?

java - 在 Synth xml 中设置 JLabel 图标

c# - 与 Func<in T1, out TResult> 作为参数的协变/逆变

java - 在 JPA 中使用泛型 @OneToMany

go - 递归结构反射错误 : panic: reflect: Field of non-struct type

java - 使用反射来调用采用不同参数的方法

java - 如何在java中绘制正方形并将值放入其中?

Java - 从 "http://www.example.com/something.php?id=1111"获取文件名

Swift 泛型,类型在运行时首先已知

java - 如何通过反射获取这个Method对象?