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

Kat*_*ona 6 java guava

ImmutableList文件说:

尽管此类不是最终的,但它不能被子类化,因为它没有公共或受保护的构造函数.

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

dim*_*414 5

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

您可以:

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

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

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


要具体解决这一点:

可以ImmutableListcom.google.common.collect包中创建一个子类(因为它的构造函数不是私有的,但是包私有),它是可变的.

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


Evg*_*eev 3

即使你扩展了,ImmutableList你也无法使其可变,因为它的所有修改器方法都是最终的,如下所示:

  public final void add(int index, E element) {
    throw new UnsupportedOperationException();
  }
Run Code Online (Sandbox Code Playgroud)

并且它的迭代器返回UnmodifiableIterator其删除方法也是最终的

  • 当然我可以通过声明另一个方法使其可变,比如说 doAdd(E element) 方法,该方法会将元素添加到列表中 (2认同)