检查Java中整个集合的类型

问题描述

我正在为removeAll一个方法ArrayList。通过该接口,removeAll一个Collection<?>,但是,出于任何原因,我都希望Collection只能是String个。有没有办法一次针对整个Collection执行此操作?

(我并不是说要单独遍历每个元素,就像这样:

for (Object el : c) {
    if (!(el instanceof String)) {
        throw new ClassCastException(String.format("Object %s is not of type String.",el.toString()));
    }
}

这是我的备份,但我希望一次检查整个Collection。)

我确实尝试过:

public boolean removeAll(Collection<?> c) {
    return subMethod((Collection<? extends String>) c,true); //true is unimportant here
}

但这只是将任何Collection<Wrapper of Primitive>转换为Collection<String>

编辑:明确地说,我想采用其他方法来确保Collection仅包含String

解决方法

不,没有办法。

Java通过擦除实现泛型,因此Collection<>本身不知道其创建时的类型参数是什么。

仅当编译代码时,才会存在Collection上的泛型类型的概念,并且通过实现List.removeAll(),您将被该方法提供的特定签名所束缚,其中不包括{{1 }}规范,例如? extends E之类的某些方法。

此外,addAll()的界面documentation明确表示(添加了强调):

投掷:
ClassCastException-如果此列表的元素的类与指定的集合不兼容(可选)

因此,为了履行此接口的约定,仅当您自己的列表中的元素与您的特定集合类型不兼容时,才应引发异常:您不应仅引发异常因为传入的参数中的项目不兼容。这就是为什么方法签名首先不包含List.removeAll()的原因:您应该允许在集合中提供其他类型,而忽略它们,因为它们显然将不匹配任何值。您的列表。

如果您要确保给定的集合仅包含字符串,则一种选择是不实现<? extends E>接口。这有明显的缺点,但是如果您的实现是特殊的,则实现的使用者可能值得承认他们正在使用具有特殊要求的特殊类,并且不能将其交给仅知道什么的方法与广义List有关。如果这样做的话,您将拥有更大的灵活性,包括将List声明为采用removeAll()或什至可以保证仅包含String的更具体,专门,非通用的集合类型。它。

,

可能类似于:

boolean b = c.stream().allMatch(String.class::isInstance);
if(b){
      //
 }