guava的ImmutableList并不是真正不可变的

时间:2013-07-30 09:03:37

标签: java guava

ImmutableList的{​​{3}}:

  

虽然这个类不是final类,但它不能被子类化,因为它没有public或protected构造函数。

我知道这有点牵强,但是可以在ImmutableList包中创建com.google.common.collect的子类(因为它的构造函数不是私有的,但是包私有),这是可变的。从那时起,没有人获得ImmutableList的引用可以确定它确实是不可变的。这不会破坏ImmutableList的目的吗?

2 个答案:

答案 0 :(得分:5)

在一天结束时,Guava只是你正在执行的一堆二进制文件。您可以随意执行任何操作,包括违反代码提供的合同。

你可以:

  • 运行破坏Guava的自定义JVM
  • 运行单独的应用程序并操纵JVM的物理内存并打破Guava
  • 操纵Guava字节码并破坏Guava
  • 配置类加载器以加载其他字节码并中断Guava
  • 拨打sun.misc.Unsafe来打破Guava
  • 使用反射打破番石榴
  • 滥用包层次结构并破坏Guava

仅举几例。这些都不是新颖的,unique to Guavaunique to Java。这是你的机器,你应该能够做这些事情。当然,你可以做的和你应该做的是完全不同的事情。以任何方式滥用Java都会给您和试图运行代码的任何其他人带来问题。

Java类型系统,包括可见性限制,不是警察。它的存在是为了帮助您编写易于使用的高质量代码。 Guava利用Java的记录行为为您提供更多工具,使您能够编写更易于使用的更高质量的代码。如果你选择打破那些你的特权工具。但不要指望任何人想要使用您的代码。

专门针对这一点:

  

可以在ImmutableList包中创建com.google.common.collect的子类(因为它的构造函数不是私有的,但是包私有),这是可变的。

你可以在没有太多工作的情况下,以同样的方式操纵私有构造函数类变为可变。如上所述,滥用包层次结构只是您不应该做的许多事情之一。如果您不相信某个第三方代码在这方面表现良好,则不应使用它。

答案 1 :(得分:3)

即使你扩展ImmutableList,你也无法使它变得可变,因为它的所有mutator方法都是最终的,就像这样:

  public final void add(int index, E element) {
    throw new UnsupportedOperationException();
  }

及其迭代器返回UnmodifiableIterator,其删除方法也是最终的