他们为什么决定让接口具有"可选操作"

Car*_*cas 6 java interface

ImmutableSet实现了Set接口.对a无意义的函数ImmutableSet现在称为"可选操作" Set.我假设这样的情况.所以ImmutableSet现在抛出UnsupportedOperationException许多可选操作.

这似乎是我的倒退.我被告知接口是一个契约,因此您可以在不同的实现中使用强制功能.可选操作的方法似乎从根本上改变(矛盾?)接口的意图.今天实现这一点我将Set接口分为两个接口:一个用于不可变操作,另一个用于扩展这些操作用于mutator.(很快,脱掉袖口解决方案)

我知道技术会发生变化.我不是说它应该以某种方式完成.我的问题是,这种变化是否反映了Java的一些基本理念的变化?让事情向后兼容只是更多的乐队吗?我对Interfaces的理解不完整吗?

Boa*_*ann 9

Java集合API设计常见问题解答详细介绍这个问题:

问:为什么不直接在核心集合接口中支持不可变性,以便您可以取消可选操作(和UnsupportedOperationException)?

答:这是整个API中最具争议的设计决策.显然,静态(编译时)类型检查是非常需要的,并且是Java中的标准.如果我们认为可行,我们会支持它.遗憾的是,尝试实现此目标会导致接口层次结构的大小爆炸,并且无法成功消除对运行时异常的需求(尽管它们会大幅减少).

Doug Lea编写了一个流行的Java集合包,确实反映了其界面层次结构中的可变性区别,根据用户对其集合包的体验,他不再认为这是一种可行的方法.用他的话来说(来自个人通信)"就像我说的那样痛苦,强大的静态类型对Java中的集合接口不起作用."

为了说明血腥细节中的问题,假设您想要将可修改性的概念添加到层次结构中.您需要四个新接口:ModifiableCollection,ModifiableSet,ModifiableList和ModifiableMap.以前简单的层次结构现在是一个混乱的层次结构.此外,您需要一个新的Iterator接口,用于不可修改的集合,不包含remove操作.你现在可以取消UnsupportedOperationException吗?不幸的是.

考虑数组.它们实现了大部分List操作,但没有删除和添加.它们是"固定大小"的列表.如果要在层次结构中捕获此概念,则必须添加两个新接口:VariableSizeList和VariableSizeMap.您不必添加VariableSizeCollection和VariableSizeSet,因为它们与ModifiableCollection和ModifiableSet相同,但您可以选择添加它们以保持一致性.此外,您还需要一种不支持添加和删除操作的新型ListIterator,以及不可修改的List.现在我们有十到十二个接口,再加上两个新的Iterator接口,而不是原来的四个接口.我们完了吗?没有.

考虑日志(例如错误日志,审计日志和可恢复数据对象的日志).它们是自然的仅附加序列,支持除remove和set(replace)之外的所有List操作.它们需要一个新的核心接口和一个新的迭代器.

那么不可变的集合呢,而不是不可修改的集合呢?(即,客户无法更改的集合,并且不会因任何其他原因而更改).许多人认为这是最重要的区别,因为它允许多个线程同时访问集合而无需同步.将此支持添加到类型层次结构需要另外四个接口.

现在我们有大约20个接口和5个迭代器,而且几乎可以肯定的是,在实践中仍然存在不能完全适合任何接口的集合.例如,Map返回的集合视图是自然删除集合.此外,有些集合会根据它们的值拒绝某些元素,因此我们仍然没有废除运行时异常.

当一切都说完了之后,我们觉得通过提供一小组可以引发运行时异常的核心接口来回避整个问题是一个合理的工程折衷方案.

简而言之,Set使用可选操作之类的接口来防止所需的不同接口数量呈指数级增长.它并不像"不可变"和"可变"那么简单.ImmutableSet然后,Guava Set必须实现与所有其他使用Sets的代码互操作.它并不理想,但实际上没有更好的方法.