java - 在运行时 : works in some cases, 获取泛型类型,但在其他运行时获取泛型类型 - 为什么?

标签 java generics dynamic

我正在尝试获取类或接口(interface)实现的通用类型。我知道这有一些风险和怪癖,但我试图了解什么是可能的。

这是我的示例代码:

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.LinkedList;

public class Main {

    public interface MyInterface<T> {
    }

    public static class BaseImpl<T> implements MyInterface<T> {
    }

    public static class TypedImpl extends BaseImpl<Integer> {
    }

    public static void main(String[] args) throws Exception {
        LinkedList<MyInterface<Integer>> instances = new LinkedList<>();

        // 1. anonymous class from interface
        instances.add(new MyInterface<Integer>() {
        });

        // 2. class extending interface
        instances.add(new BaseImpl<Integer>());

        // 3. class with pre-defined generic type
        instances.add(new TypedImpl());

        for (MyInterface<Integer> instance : instances) {
            System.out.println("----------------------------------------------");

            Class clazz = instance.getClass();
            Type genericSuper = clazz.getGenericSuperclass();
            Type[] genericInterfaces = clazz.getGenericInterfaces();
            Class target = null;

            System.out.println("class: " + clazz.getName());
            System.out.println("generic super: " + genericSuper);
            System.out.println("generic interfaces: " + Arrays.asList(genericInterfaces));

            // attempt to 'extract' generic type
            if (genericSuper instanceof ParameterizedType) {
                target = getGeneric((ParameterizedType) genericSuper);
            } else if (genericInterfaces.length > 0) {
                for (Type genericInterface : genericInterfaces) {
                    if (genericInterface instanceof ParameterizedType) {
                        target = getGeneric((ParameterizedType) genericInterface);

                        if (null != target) {
                            break;
                        }
                    }
                }
            }

            System.out.println("TARGET: " + target);
        }
    }

    // attempt to get type argument
    public static Class getGeneric(ParameterizedType type) {
        if (MyInterface.class.isAssignableFrom((Class) type.getRawType())) {
            Type typeArg = type.getActualTypeArguments()[0];

            try {
                return (Class) typeArg;
            } catch (ClassCastException e) {
                System.out.println("cast exception for '" + typeArg + "'");
            }
        }

        return null;
    }

}

这个的输出是:

----------------------------------------------
class: Main$1
generic super: class java.lang.Object
generic interfaces: [Main.Main$MyInterface<java.lang.Integer>]
TARGET: class java.lang.Integer
----------------------------------------------
class: Main$BaseImpl
generic super: class java.lang.Object
generic interfaces: [Main.Main$MyInterface<T>]
cast exception for 'T'
TARGET: null
----------------------------------------------
class: Main$TypedImpl
generic super: Main.Main$BaseImpl<java.lang.Integer>
generic interfaces: []
TARGET: class java.lang.Integer

因此,我的目标是让 target 变量的值为 Integer.class。对于匿名类 (#1) 和显式类型实现 (#3),我能够按预期找到目标。为什么它在这些实例中起作用而不是在#2(BaseImpl 实例)的情况下?还有另一种方法可以做到这一点吗? (我知道通过实现类的构造函数传递目标 Class 的常见解决方法,但是我对动态执行此操作很感兴趣)

我引用了以下资源:

提前致谢

阿贝尔

最佳答案

来自 http://tutorials.jenkov.com/java-reflection/generics.html (粗体是我的)

Using Java Generics typically falls into one of two different situations:

Declaring a class/interface as being parameterizable. Using a parameterizable class. When you write a class or interface you can specify that it should be paramerizable. This is the case with the java.util.List interface. Rather than create a list of Object you can parameterize java.util.List to create a list of say String.

When runtime inspecting a parameterizable type itself, like java.util.List, there is no way of knowing what type is has been parameterized to. This makes sense since the type can be parameterized to all kinds of types in the same application. But, when you inspect the method or field that declares the use of a parameterized type, you can see at runtime what type the paramerizable type was parameterized to. In short:

You cannot see on a type itself what type it is parameterized to a runtime, but you can see it in fields and methods where it is used and parameterized. Its concrete parameterizations in other words.

特殊情况在页面上解释

关于java - 在运行时 : works in some cases, 获取泛型类型,但在其他运行时获取泛型类型 - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32716797/

相关文章:

java - 在 java 中通过 objectoutputstream 发送字节数组

java - 使用for循环为多个 ImageView 设置图像资源

java - 方法签名中的 <E> 是什么?

java - 递归泛型

java - 为什么这个泛型方法不接受任何类型?

java - 获取泛型类型参数的正确方法

php - MySQL - 带有变量的 SELECT 查询不会执行

c# - 如何发出 default(TimeSpan) 作为可选参数的默认值

javascript - 如何在附加html代码后获取ready事件

java - 如何确定实际安装的 maven-gpg-plugin 的版本?