检查空集合的Java集合通用类型

时间:2012-09-08 12:02:26

标签: java

我想实现以下功能:

public boolean checkType(Vector<?> vec)
{
  // return true if its Vector<Integer> and false otherwise
}

如何检查矢量元素类型? 注意向量可能为空,因此我无法检查第一个元素是“instanceof”Integer还是String ...

编辑:

嗯,我有一些想法,我不知道它是否会起作用

我可以按如下方式实现checkType函数:

public <T> boolean checkType(Vector<T> vec)
{
  // return true if T is Integer and false otherwise
}

是否可以检查T是否为整数?!

先谢谢

4 个答案:

答案 0 :(得分:4)

由于type erasure

通用类型参数在运行时是不可恢复的(某些特殊情况除外)。这意味着在运行时,Vector<Integer>Vector<String>只是Vector个,它们的元素只是Object引用。

只有实际的运行时类(可以通过instanceof检测出来)检查各个元素的元素类型的概念,否则Vector本身不知道它的元素类型是什么。

所以基本上,任何类型的空向量等于任何其他类型的向量。这样投射甚至是安全的:

Vector<String> noStrings = (Vector<String>) new Vector<Integers>();

但是有一个问题,因为虽然你可以说向量符合任何必需的元素类型,但只要向量保持为空,此语句只能。因为如果你这样做:

Vector<Integer> ints = new Vector<Integer>(); // empty
Vector<String> strings = (Vector<String>) ints; // unchecked warning, but still possibly ok
ints.add(1); // here comes trouble
String s = strings.get(1); // oh oh, ClassCastException

编辑:

回答第二个问题:不可能写下这样的东西:

public <T> boolean checkType(Vector<T> vec) {
    return T instanceof Integer; // impossible
    return T == Integer; // impossible
    return T.class == Integer.class // impossible
    return vec instanceof (Vector<Integer>); // impossible
}

但是,您可以编写一个使用类标记作为输入参数的方法:

static <T> boolean checkElementType(Collection<?> collection, Class<T> elementType) {
    for (Object object : collection) {
        if (!elementType.isAssignableFrom(object.getClass())) {
            return false;
        }
    }
    return true;
}

然后你可以像这样使用它:

List<?> list1 = Arrays.asList(1, 2, 3);
List<?> list2 = Arrays.asList(1, 2, 3, "a");
System.out.println(checkElementType(list1, Integer.class)); // true
System.out.println(checkElementType(list2, Integer.class)); // false

答案 1 :(得分:2)

任何告诉你这完全可能的人都是错的。在运行时,无法判断空Vector是Vector<Integer>还是Vector<Rainbow>

这或多或少都是类型擦除的定义

答案 2 :(得分:2)

由于类型擦除,这是不可能的。

即使向量不为空,集合库也没有提供真正的保护,防止将不同类型的东西放入:

    Vector v = new Vector<Integer>();
    v.add("foo");
    System.out.println(v.get(0));

将无错误地运行并很好地打印不应该被允许的字符串值。

因此,即使通过检查第一个元素的类型,在运行时确定泛型类型的任何尝试都是不可靠的。

您可以在自己的通用代码中执行的操作是添加构造函数参数和包含该值的字段,以便您的代码 在运行时知道该类型。

这种策略难以应用于整个馆藏库,但Vector的开头就是:

public class TypedVector<E> extends Vector<E> {

    private Class<E> genericClass;

    public TypedVector(Class<E> clazz) {
        super();
        this.genericClass = clazz;
    }

    // many other constructors ... but probably not all of them

    public Class<?> getGenericClass() {
        return genericClass;
    }

    @Override
    public boolean add(E e) {
        if (!(genericClass.isAssignableFrom(e.getClass())))
                throw new IllegalArgumentException("Incorrect class");
        return super.add(e);
    }

    // many other overrides for run-time type safety
}

答案 3 :(得分:-2)

public boolean checkType(Vector<?> vec)
{
  if(!vec.isEmpty())
  {
    if("String".equals(vec.get(0).getClass().getSimpleName()))
             return false;
    else if("Integer".equals(vec.get(0).getClass().getSimpleName()))
             return true;               
   }
}

希望这会有所帮助!!