有可能找出一些列表是否固定大小?

时间:2017-07-07 16:13:22

标签: java

是否有可能找出一些列表是否固定大小? 我的意思是,例如这段代码:

String[] arr = {"a", "b"};
List<String> list = Arrays.asList(array);

返回由数组支持的固定大小List。但是,如果List是固定大小而不尝试添加/删除元素并捕获异常,是否有可能以编程方式理解?例如:

try {
    list.add("c");
}
catch(UnsupportedOperationException e) {
    // Fixed-size?
}

4 个答案:

答案 0 :(得分:14)

String[]

创建的列表
List<String> list = Arrays.asList(array);

Arrays作为封闭类,而由new ArrayList()创建的一个将不具有封闭类。因此,以下内容应该可以检查List是否是由于调用Arrays.toList()生成的:

static <T> boolean wasListProducedAsAResultOfCallingTheFunctionArrays_asList(List<T> l) {
    return Arrays.class.equals(l.getClass().getEnclosingClass());
}

请注意,此方法依赖于未记录的行为。如果他们将另一个嵌套的List子类添加到Arrays类,它将会中断。

答案 1 :(得分:6)

  

是否可以查明某些列表是否为固定大小?

理论上 - 否。固定大小是列表类实现的新兴属性。您只能通过尝试添加元素来确定列表是否具有该属性。

请注意,简单的行为测试无法可靠地区分固定大小的列表和有界列表,或者永久或暂时只读的列表。

实际上,固定大小的列表通常与普通的列表具有不同的类别。您可以测试对象的类,以查看它是否是特定的类。因此,如果您了解用于在代码库中实现固定大小的列表 ,那么您可以测试特定列表是否是固定大小的。

例如,Arrays.asList(...)方法返回实际类为List的{​​{1}}对象。这是一个私有嵌套类,但您可以使用反射查找它,然后使用java.util.Arrays.ArrayList来测试它。

然而,这种方法很脆弱。如果Object.getClass().equals(...)的实现被修改,或者您开始​​使用其他形式的固定大小列表,您的代码可能会中断。

答案 2 :(得分:2)

没有

无论List是否可扩展,List API都是相同的,deliberate

List API中也没有任何内容允许您查询它以确定此功能。

您无法通过反射完全可靠地确定此信息,因为您将依赖于实现的内部详细信息,并且因为存在可能固定大小的无限数量的类。例如,除Arrays.asList之外,还有Arrays.asList().subList,它恰好返回不同的类。基本列表周围也可能有包装,如Collections.checkedListCollections.synchronizedListCollections.unmodifiableList。还有其他固定大小的列表:Collections.emptyListCollections.singletonListCollections.nCopies。在标准库之外,还有Guava的ImmutableList之类的东西。通过扩展AbstractList手动滚动列表也是非常简单的(对于固定大小的列表,您只需要实现size()get(int)方法)。

即使您检测到列表不是固定大小,List.add的规范也允许它出于其他原因拒绝元素。例如,Collections.checkedList包装器会为不需要的类型的元素抛出ClassCastException

即使你知道你的列表是可扩展的,并允许任意元素,这并不意味着你想要使用它。也许它是同步的,或者不是同步的,或者是不可序列化的,或者它是一个慢速的链表,或者是你不想要的其他质量。

如果你想控制列表的类型,可变性,可串行性或线程安全性,或者你想确保没有其他代码保留对它的引用,那么你可以自己创建一个新的代码。在不必要的情况下(memcopies速度极快)这样做并不昂贵,并且它可以让你更明确地了解你的代码在运行时实际会做什么。如果您真的想避免创建不必要的副本,请尝试白名单,而不是将列表类列入黑名单。例如:

if (list.getClass() != ArrayList.class) {
    list = new ArrayList<>(list);
}

(注意:这使用getClass代替instanceof,因为instanceof对于ArrayList的任何奇怪子类也都适用。)

答案 3 :(得分:0)

java-9中有不可变的集合,但是仍然没有常见的@Immutable注释或者我们可以查询以获取此信息的公共标记接口。

我能想到的最简单的方法就是获取这样一个实例的类的名称:

String nameList = List.of(1, 2, 3).getClass().getName();
System.out.println(nameList.contains("Immutable"));

但仍然依赖于内部细节,因为它查询公​​共类ImmutableCollections的名称,这不是公开的,显然可以更改,恕不另行通知。