来自Collections Framework Overview:
不支持修改操作的集合(例如添加,删除和清除)称为不可修改 . 不可修改的集合是可修改的 . 另外保证Collection对象中没有可见变化的集合称为不可变 . 不可变的集合是可变的 .
我无法理解这种区别 .
这里不可修改和不可变的区别是什么?
来自Collections Framework Overview:
不支持修改操作的集合(例如添加,删除和清除)称为不可修改 . 不可修改的集合是可修改的 . 另外保证Collection对象中没有可见变化的集合称为不可变 . 不可变的集合是可变的 .
我无法理解这种区别 .
这里不可修改和不可变的区别是什么?
6 回答
不可修改的集合通常是可修改集合的包装,其他代码可能仍然可以访问 . 所以虽然你可以依靠不改变的内容 .
不可变集合保证不再有任何东西可以改变集合 . 如果它包装了一个可修改的集合,它确保没有其他代码可以访问该可修改的集合 . 请注意,虽然没有代码可以更改集合包含引用的对象,但是对象本身可能仍然是可变的 - 创建
StringBuilder
的不可变集合并不以某种方式"freeze"这些对象 .基本上,区别在于其他代码是否能够改变背后的集合 .
基本上
unModifiable
集合是一个视图,所以间接它可能仍然是来自其他一些可修改的引用的'modified' . 此外,它只是一个 readonly view 的另一个集合,当源集合更改时,unModifiable Collection将始终显示最新值 .但是
immutable
Collection可以视为另一个集合的 readonly copy ,无法修改 . 在这种情况下,当源集合发生更改时,不可变集合不会反映更改这是一个可视化这种差异的测试用例 .
Output
我认为主要区别在于可变集合的所有者可能希望提供对其他代码的集合访问,但是通过不允许其他代码修改集合的接口提供该访问(同时保留该功能)拥有代码) . 因此集合不是不可变的,但某些用户不允许更改集合 .
Oracle的Java Collection Wrapper tutorial有这样说(重点补充):
如果我们谈论JDK
Unmodifiable*
vs guavaImmutable*
,实际上差异也在 performance . 如果它们是常规集合的包装器(JDK实现是包装器),则不可变集合可以更快,更高效 . Citing the guava team:JDK提供了Collections.unmodifiableXXX方法,但在我们看来,这些方法可以
<...>
引用The Java™ Tutorials:
(强调我的)
这真的总结了 .
如上所述,不可修改不像是不可变的,因为如果例如不可修改的集合具有由其他对象引用的底层委托集合并且该对象改变它,则可以改变不可修改的集合 .
关于不可变的,它甚至没有明确定义 . 但是,通常它意味着对象“不会改变”,但需要递归地定义 . 例如,我可以在类上定义不可变,其实例变量都是基元,并且其方法都不包含参数和返回基元 . 然后,这些方法递归地允许实例变量是不可变的,并且所有方法都包含不可变的参数并返回不可变的值 . 应保证方法随时间返回相同的值 .
假设我们可以做到这一点,那么概念线程也是安全的 . And you might be led to believe that immutable (or not changeble over time) also implies thread safe. However that is not the case 这是我在这里提出的主要观点,在其他答案中尚未注意到 . 我可以构造一个永远返回相同结果但不是线程安全的不可变对象 . 为了看到这一点,假设我通过随时间保持添加和删除来构造不可变集合 . 现在,immutable集合通过查看内部集合(可能随时间变化)返回其元素,然后(内部)添加和删除在创建集合后添加或删除的元素 . 显然,虽然集合总是返回相同的元素,但它不是线程安全的,仅仅因为它永远不会改变 Value .
现在我们可以将不可变的对象定义为线程安全且永远不会更改的对象 . 有一些指导用于创建通常会导致此类的不可变类,但请记住,可能存在创建不可变类的方法,这需要注意线程安全性,例如,如上面的“快照”集合示例中所述 .