Java 中的 Collections.checkedList() 调用是什么?

问题描述 投票:0回答:4

我只是想知道

java.util.Collections.checkedList()
实际用途是什么。

我有一些代码,我知道它会返回一个

List<String>
,但它是通过一系列消息传递调用传递并作为
java.io.Serializable
返回给我的。 checkList 调用是否适合我将我的
Serializable
变成
List<String>
? 我知道我可以将其转换为
java.util.List
,但我不想检查每个元素,而且我不愿意假设每个元素都是
String

java generics collections
4个回答
19
投票

它部分用作调试工具,用于查找代码插入错误类型的类的位置,以防您看到这种情况发生,但无法弄清楚在哪里。

您可以将其用作提供集合的公共 API 的一部分,并且您希望确保该集合中不会包含错误类型的任何内容(例如,如果客户端删除了泛型)。

您可以在您的案例中使用它的方式是:

 Collections.checkedList(
      new ArrayList<String>(uncertainList.size()), String.class)
      .addAll(uncertainList);

如果没有引发异常,那么您就知道自己做得很好。这并不完全是一段性能优化的代码,但如果列表内容相当小,应该没问题。


19
投票

不完全是:

Collections.checkedList
只会装饰列表以防止将来插入错误类的对象,它不会检查列表中已有的所有元素。

但是,您可以创建一个新的 checkList,然后调用

addAll
并传入您不确定的列表 - 而不是自己编写循环。


11
投票

有关

checkedList
用途的讨论可在 checkedCollection 的文档中找到。给出的理由是:

  • 作为调试辅助(如果有人使用了未经检查的强制转换)
  • 确保传递由第三方代码填充的集合时的安全。

您可以使用 google collections 中的以下内容来检查列表是否仅包含字符串:

Iterables.all(list, Predicates.instanceOf(String.class))

0
投票

让我们想象一下以下场景:您有一个您知道的类型的列表,例如数字列表。并且您有一个第三方 API,它接受一个列表(不指定类型)。此 API 可能会导致输入列表中出现一些突变(比方说),并且您需要确保第 3 方 API 不会向您的列表中添加其他类型。

一点上下文:(请阅读更多关于擦除的内容)在运行时,泛型变成了对象。

假设您有以下方法:

    private static final String STRING_VALUE = "this is actually a string!";
    public void addElements(List l) {
        l.add(STRING_VALUE);
        System.out.println(l);
    }

编译时没问题,因为 List 没有指定类型,但你有不安全的代码,这是 Ben 正在讨论的代码示例。

让我们在数字数组列表上测试这个方法:

    @Test
    public void addingAStringInANumbersList_shouldBeSuccessful() {
        List<Number> numbers = new ArrayList<>(List.of(1, 2, 3, 1.0, 2.0f, 3.0f, 5));

        addElements(numbers);

        Assertions.assertEquals(List.of(1, 2, 3, 1.0, 2.0f, 3.0f, 5, STRING_VALUE), numbers);
    }

如果运行上面的代码,就会通过。为什么?因为泛型在运行时被替换为对象,所以列表在运行时是类型安全的,只是在运行时。

让我们尝试检查集合:

    @Test
    public void addAStringInACheckedList_shouldFail() {
        List<Number> numbers = Collections.checkedList(new ArrayList<>(List.of(1, 2, 3, 1.0, 2.0f, 3.0f, 5)), Number.class);

        Assertions.assertThrows(ClassCastException.class, () -> addElements(numbers));
    }

这将抛出 ClassCastException,这是测试所期望的 => 它将通过。因此,检查的集合可以帮助您处理遗留的第 3 方代码。

PS:Collections 实用程序类仅创建包装器,因此如果您将“核心”集合传递给不安全的第 3 方代码,结果将在检查的集合包装器上可见,例如:

    @Test
    public void addingAStringInANumbersList_theCheckedListIsJustAWrapper_shouldBeSuccessful() {
        List<Number> numbers = new ArrayList<>(List.of(1, 2, 3, 1.0, 2.0f, 3.0f, 5));
        List<Number> checkedNumbers = Collections.checkedList(numbers, Number.class);

        addElements(numbers);

        Assertions.assertEquals(List.of(1, 2, 3, 1.0, 2.0f, 3.0f, 5, STRING_VALUE), numbers);
        Assertions.assertEquals(List.of(1, 2, 3, 1.0, 2.0f, 3.0f, 5, STRING_VALUE), checkedNumbers);
    }

我希望现在检查收藏的目的已经明确。

© www.soinside.com 2019 - 2024. All rights reserved.