当前位置: 首页 > 面试题库 >

番石榴的ImmutableXXX真的不可变吗?

严修谨
2023-03-14
问题内容

我已经使用番石榴已有一段时间了,并且对此感到非常信任,直到昨天我偶然发现了一个例子,这让我开始思考。长话短说,这里是:

 public static void testGuavaImmutability(){
     StringBuilder stringBuilder = new StringBuilder("partOne");
     ImmutableList<StringBuilder> myList = ImmutableList.of(stringBuilder);
     System.out.println(myList.get(0));
     stringBuilder.append("appended");
     System.out.println(myList.get(0));
 }

运行此命令后,您可以看到 ImmutableList 内部的条目的值已更改。如果此处涉及两个线程,则一个线程可能碰巧看不到另一个线程的更新。

同样令我非常不耐烦的是,Effective Java中的Item15,第5点说:

在构造函数中制作防御程序副本 -看起来很合理。

查看ImmutableList的源代码,我看到以下内容:

 SingletonImmutableList(E element) {
     this.element = checkNotNull(element);
 }

因此,虽然我不知道在这种情况下将如何实现通用的深层副本(可能是序列化?),但实际上没有副本。

那么..为什么他们叫不可变?


问题答案:

您在这里得到的是 不可变深度不可变 之间的区别

一个不变的对象永远不会改变,但是它所指的任何东西都可能会改变。深不变性是更强的:既不是基本对象,也可以导航到任何对象 它会改变。

每种情况都适合自己的情况。当您创建自己的具有类型字段的类时Date,该日期 您的对象所有;这确实是它的一部分。因此,你应该做的防守拷贝它(在途中
出路!)提供深层不变性。

但是一个集合并没有真正“拥有”它的元素。它们的状态不被视为集合状态的一部分。这是一种不同的类- 容器
。(此外,正如您所暗示的那样,它对所使用的元素类型没有深入的了解,因此它仍然不知道如何复制元素。)

另一个答案指出,番石榴收藏应该使用术语 unmodifiable 。但条款之间有非常明确的差异 不可修改不可变
的集合的情况下,它无关浅与深不变性。“ 无法修改”表示 无法通过引用更改此实例;“不可变”表示无论您或其他任何参与者,此实例都无法更改。



 类似资料:
  • 问题内容: 我最近了解了Java中EnumMap的好处,并希望将现有的替换为EnumMap。但是,我也想要ImmutableMap提供的不可变属性。 番石榴中有可用的ImmutableEnumMap变体吗? 在存储方面,哪个(EnumMap与ImmutableMap)的性能更好? 我找不到两者的比较。如果有人可以将我指向某个链接或对这两种数据结构的效率提供一些见解,我将不胜感激? 问题答案: 番石

  • 我非常喜欢Java8流和Guava的不可变集合,但我不知道如何将两者结合使用。 例如,如何实现将流结果收集到不可变多映射中的Java 8收集器? 奖励点:我希望能够提供键/值映射器,类似于Collectors.toMap()的工作方式。

  • 问题内容: 刚刚发现了Guava库项目。 这些与GWT兼容吗? 问题答案: 从该页面的介绍性PDF中, 您可以在…上使用这些库。 在JDK 6上 在Android上, 我们认为。需要志愿者来帮助我们进行测试。 在Google App Engine上, 我们认为。需要志愿者来帮助我们进行测试。 在GWT上-参差不齐! 由于GWT的JDK库支持 可能参差不齐,也许是2/3,所以到目前为止,这些库中的东

  • 问题内容: 我在commons- lang中使用了简单的DTO。现在,我尝试使用Google Guava代替Apache Commons库。我在番石榴找到了。但是如果班上有很多成员,这太冗长了。例如: 如果我使用commons-lang,则简单得多: 有什么更好的方法可以用Guava而不是commons-lang 来实现? 番石榴文件 问题答案: 我有番石榴的小招。我将 IntelliJ IDEA

  • 问题内容: Apache Commons IO 有一个很好的便捷方法IOUtils.toString()来读取字符串。 由于我正尝试从Apache Commons转移到Guava:Guava中有与之等效的产品吗?我查看了包中的所有类,但几乎找不到任何简单的东西。 编辑: 我理解并赞赏字符集的问题。碰巧,我知道我所有的来源都是ASCII(是,ASCII,不是ANSI等),因此在这种情况下,编码对我来

  • 问题内容: 我想知道哪个更有效,为什么? 1) 要么 2) 问题答案: 我看不出您为什么要在此处使用builder的任何原因: 比在这种情况下制作一个更具可读性, 不会推断通用类型,并且在用作单行代码时必须自己指定类型, (来自docs) 在与另一个不可变集合调用时 做得很好( 尝试避免在安全的情况下实际复制数据 ), (从源) 调用以前创建的,同时避免为零元素和一元素集合创建任何列表(分别返回空