java - 检查类型是否通用

标签 java generics

我正在尝试实现一个代码分析器,它将另一个 Java 文件作为输入。对于每个变量声明,我想检查变量所属的类型是否是通用的。有没有一种简单的方法可以做到这一点?

例如,我希望它:

isGenericType("HashSet") -> true
isGenericType("int") -> false

我可能会创建一个包含所有泛型类型的注册表,但这样做的问题是如果我实现自定义泛型类型,那么我每次都必须更新注册表。对此有一些简单的解决方案吗?

最佳答案

这将按对象、类或类名进行测试。

更新:根据有用的评论对该代码进行了多次修订,提供了一些有趣的测试用例。然而,最终问题的适当解决方案取决于问题是如何定义的。请引用早期的修订和评论。

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;

public class GenericTest
{
    public static void main(String[] args)
    {
        try
        {
            new GenericTest().testAll();
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }

        System.exit(0);
    }

    public void testAll() throws ClassNotFoundException, InstantiationException, IllegalAccessException
    {
        Object a = new HashMap<String, Object>();
        Object b = new HashMap();
        int c = 0;

        isGeneric(a);
        System.out.println("\n");
        isGeneric(b);
        System.out.println("\n");
        isGeneric(c);
        System.out.println("\n");
        isGeneric("java.util.HashMap");
        System.out.println("\n");
        isGeneric("java.lang.Integer");
        System.out.println("\n");

        isGeneric(new TestA());
        System.out.println("\n");
        isGeneric(new TestB());
        System.out.println("\n");
        isGeneric(new TestB<String>());
        System.out.println("\n");
        isGeneric(new TestC());
        System.out.println("\n");
        isGeneric(new TestD());
        System.out.println("\n");
        isGeneric(new TestE());
        System.out.println("\n");

        return;
    }

    public static void isGeneric(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException
    {
        GenericTest.isGeneric(Class.forName(className));
        return;
    }

    public static boolean isGeneric(Object o)
    {
        return isGeneric(o.getClass());
    }

    public static boolean isGeneric(Class<?> c)
    {
        boolean hasTypeParameters = hasTypeParameters(c);
        boolean hasGenericSuperclass = hasGenericSuperclass(c);
//      boolean hasGenericSuperinterface = hasGenericSuperinterface(c);
//      boolean isGeneric = hasTypeParameters || hasGenericSuperclass || hasGenericSuperinterface;
        boolean isGeneric = hasTypeParameters || hasGenericSuperclass;

        System.out.println(c.getName() + " isGeneric: " + isGeneric);

        return isGeneric;
    }

    public static boolean hasTypeParameters(Class<?> c)
    {
        boolean flag = c.getTypeParameters().length > 0;
        System.out.println(c.getName() + " hasTypeParameters: " + c.getTypeParameters().length);
        return flag;
    }

    public static boolean hasGenericSuperclass(Class<?> c)
    {
        Class<?> testClass = c;

        while (testClass != null)
        {
            Type t = testClass.getGenericSuperclass();

            if (t instanceof ParameterizedType)
            {
                System.out.println(c.getName() + " hasGenericSuperclass: " + t.getClass().getName());
                return true;
            }

            testClass = testClass.getSuperclass();
        }

        return false;
    }

    public static boolean hasGenericSuperinterface(Class<?> c)
    {
        for (Type t : c.getGenericInterfaces())
        {
            if (t instanceof ParameterizedType)
            {
                System.out.println(c.getName() + " hasGenericSuperinterface: " + t.getClass().getName());
                return true;
            }
        }

        return false;
    }

    public interface TestX<X> { }

    public interface TestY extends TestX<String> { }

    public class TestA implements TestY { }

    public class TestB<V> extends TestA { }

    public class TestC extends TestB<String> { }

    public class TestD extends TestA { }

    public class TestE extends TestC { }
}

运行上述代码的结果:

java.util.HashMap hasTypeParameters: 2
java.util.HashMap hasGenericSuperclass: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
java.util.HashMap isGeneric: true


java.util.HashMap hasTypeParameters: 2
java.util.HashMap hasGenericSuperclass: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
java.util.HashMap isGeneric: true


java.lang.Integer hasTypeParameters: 0
java.lang.Integer isGeneric: false


java.util.HashMap hasTypeParameters: 2
java.util.HashMap hasGenericSuperclass: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
java.util.HashMap isGeneric: true


java.lang.Integer hasTypeParameters: 0
java.lang.Integer isGeneric: false


GenericTest$TestA hasTypeParameters: 0
GenericTest$TestA isGeneric: false


GenericTest$TestB hasTypeParameters: 1
GenericTest$TestB isGeneric: true


GenericTest$TestB hasTypeParameters: 1
GenericTest$TestB isGeneric: true


GenericTest$TestC hasTypeParameters: 0
GenericTest$TestC hasGenericSuperclass: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
GenericTest$TestC isGeneric: true


GenericTest$TestD hasTypeParameters: 0
GenericTest$TestD isGeneric: false


GenericTest$TestE hasTypeParameters: 0
GenericTest$TestE hasGenericSuperclass: sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
GenericTest$TestE isGeneric: true

关于java - 检查类型是否通用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30877594/

相关文章:

java - 是否可以从 Thymeleaf 中的 Controller 更新多个模板?

C# 泛型 & 不会发疯

ios - 为什么协议(protocol)的存在元类型会丢失继承信息?

java - 我必须用 Java 创建一个月份类

java接口(interface)方法输入本身

java - recyclerview 不显示来自 Json 的多个数据

java - 创建通用对象的缓存

java - 如何将方法重构为仅接受类型子集的通用方法?

java - 实现通用接口(interface)

java - 自定义对象数组的 Class.forName