Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
给定一个集合,获取项的类型(Java)_Java_Oop_Reflection_Introspection - Fatal编程技术网

给定一个集合,获取项的类型(Java)

给定一个集合,获取项的类型(Java),java,oop,reflection,introspection,Java,Oop,Reflection,Introspection,我需要获取集合中项目的类型。 为了检索单个实例的类,我使用以下代码: classUnderTest.getName() 但是,如何检索以下集合的项的类 Collection collection = (Collection) getCollection.invoke(instance1); 由于一般擦除,集合对象不知道项必须是什么类型,只知道它们现在是什么。根据您的需要,一种解决方案可能是通过艰难的方式找到集合中所有项的最特定超类(或超级接口) Collection c = ...

我需要获取集合中项目的类型。 为了检索单个实例的类,我使用以下代码:

classUnderTest.getName()
但是,如何检索以下集合的项的类

Collection collection = (Collection) getCollection.invoke(instance1);

由于一般擦除,集合对象不知道项必须是什么类型,只知道它们现在是什么。根据您的需要,一种解决方案可能是通过艰难的方式找到集合中所有项的最特定超类(或超级接口)

    Collection c = ...
    Iterator it = c.iterator();
    if (c.hasNext()) {
        Class clazz = c.next().getClass();
        ...
    }

但是,您真的需要知道集合项的类型吗?

由于以下原因,您无法在运行时获取/推断集合的通用类型。泛型用于编译时安全,类型信息在运行时被删除


在运行时,收集的实例是
对象
,它不关心运行时的实际类型。

简而言之,您不能

泛型类型参数不会记录为类型实例(对象)的一部分。(请阅读“”…)此外,您的示例仍然使用原始类型

您可以选择(非空)集合中的某个元素并获取该元素的类型,但它不会告诉您关于其他元素类型的任何信息。(它们可能相同…也可能不同。)如果集合为空或包含
null
引用,则您甚至无法可靠地做到这一点

无论如何,这将为您提供集合的第一个元素的类型

    Collection c = ...
    Iterator it = c.iterator();
    if (c.hasNext()) {
        Class clazz = c.next().getClass();
        ...
    }

您可以迭代整个集合,并(有一定难度)找出它们都符合的公共类或接口。但即使这样也不一定与声明的元素类型相同。

一般来说,您不能这样做。例如,集合可能为空或仅由空值组成。还有,接口呢?可能存在多个对所有集合元素都通用的接口

但是,以下其中一项可能对您的情况有所帮助:

1) 分析集合内容:假设集合非空,扫描集合中的所有项,并在类层次结构中找到它们的最低公共祖先

2) 获取已声明的泛型类型:如果正在检查的对象已声明为某个类的数据成员(带有泛型),则可以在运行时使用反射计算其已声明的泛型类型(请参阅)

--编辑--

为了练习,我实现了最低的公共祖先实用程序:

    public static Class<?> getLCA(Collection<?> c) {
        Class<?> res = null;
        for (Object obj : c)
            if (obj != null) {              
                Class<?> clazz = obj.getClass();
                res = (res == null)? clazz : getLCA(res, clazz);
            }

        return res;
    }

    private static Class<?> getLCA(Class<?> classA, Class<?> classB) {
        if (classA.isAssignableFrom(classB))
            return classA;
        if (classB.isAssignableFrom(classA))
            return classB;

        while (!classA.isAssignableFrom(classB))
            classA = classA.getSuperclass();

        return classA;
    }
公共静态类getLCA(集合c){
类res=null;
用于(对象对象对象:c)
如果(obj!=null){
Class clazz=obj.getClass();
res=(res==null)?clazz:getLCA(res,clazz);
}
返回res;
}
私有静态类getLCA(类A、类B){
如果(类别A.isAssignableFrom(类别B))
返回A类;
如果(类别B.isAssignableFrom(类别A))
返回类别B;
而(!classA.isAssignableFrom(classB))
classA=classA.getSuperclass();
返回A类;
}

效率:O(n*h),其中n是集合大小,h是类层次结构中集合项的最大深度。

您不能。在Java中,无法在运行时检索泛型类型。它被称为

但是您可以迭代
集合
,得到最通用的类型。但即使这样做,也无法将该类型作为泛型类型传递


你最好的办法是禁止警告,并确保没有任何非法信息被传递到methode中。

从大多数人所说的帖子中,答案是显而易见的。。。就是 由于以下原因,无法在运行时获取/推断集合的泛型类型:

但是,我想展示一下这意味着什么

假设
我们创建一个类MyClass
,并执行此操作

Collection<String> collection = new ArrayList<String>();

public static void main(String[] args)  {

    Field stringListField = null;
    try {
        stringListField = MyClass.class.getDeclaredField("collection");
        ParameterizedType stringListType = (ParameterizedType) stringListField.getGenericType();
        Class<?> stringListClass = (Class<?>) stringListType.getActualTypeArguments()[0];
        System.out.println(stringListClass); 

    } catch (SecurityException e) {
        e.printStackTrace();
    } catch (NoSuchFieldException e) {
        e.printStackTrace();
    }
}

这是运行时类型擦除引发的异常

是的,我需要,因为我正在为不同的类创建一些与继承无关的测试方法。然后使用所有每类测试用例创建一个
映射(或不同的接口),并运行各个项的类。您是否仍然需要查找items类,或者简单的item.getClass().getName()是否足够(对于每个item)?为什么需要它?你能举例说明吗?
sun.reflect.generics.reflectiveObjects.WildcardTypeImpl cannot be cast to java.lang.Class