java - 不可变类中的可变对象字段

标签 java immutability

我被分配在java中创建一个不可变的队列类,在这个过程中我所做的实际上是有一个私有(private)的最终数组列表、一个startIndex、一个lastIndex作为字段。每次执行排队时,我所做的就是在数组列表顶部添加新值,并返回一个具有更改的开始和最后索引值的新类实例。出列操作也以类似的方式执行。这样,在每次入队/出队操作之后,新实例都有自己的起始索引、数组列表的最后索引值,而前一个实例保留这些字段的旧值。

我的问题是我可以称这个类为不可变的吗?谢谢。

最佳答案

不,类不是一成不变的。

基本上,线程和 Java 内存模型是语言规范的一部分,因此每当您询问类的行为时都必须考虑语言的这些部分。由于 ArrayList 不是线程安全的,并且您对其进行了变异,因此您不能依赖该 ArrayList 来表现出预期的行为,例如返回其数组中的第一个或最后一个元素,多线程的存在。

Java Language Specification says:

While most of the discussion in the preceding chapters is concerned only with the behavior of code as executed a single statement or expression at a time, that is, by a single thread, the Java Virtual Machine can support many threads of execution at once. These threads independently execute code that operates on values and objects residing in a shared main memory...

Threads are represented by the Thread class. The only way for a user to create a thread is to create an object of this class; each thread is associated with such an object. A thread will start when the start() method is invoked on the corresponding Thread object.

The behavior of threads, particularly when not correctly synchronized, can be confusing and counterintuitive.

这是这里拍摄的钱,在 Section 17.4.5:

More specifically, if two actions share a happens-before relationship, they do not necessarily have to appear to have happened in that order to any code with which they do not share a happens-before relationship. Writes in one thread that are in a data race with reads in another thread may, for example, appear to occur out of order to those reads.

由于您的 ArrayList 不是线程安全的(没有发生之前关系),写入可以按任何顺序发生 - 您可能会看到内部数组被写入时的初始值初始化为空值、之前的一些写入或最近的写入。无法分辨。

所以这是违反直觉的,因为您认为如果您有一个ArrayList最后一个元素的索引,那么该ArrayList将返回其最后一个元素的值,但规范说“不”。

阅读我链接到的规范,并获取 Brian Goetz 撰写的《Java 并发实践》副本。那本书基本上是所有线程和 Java 的圣经。

关于java - 不可变类中的可变对象字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25343620/

相关文章:

java - 字符串不变性

arrays - Swift 中带有数组的 For-In 循环中迭代器元素的可变性

javascript - 在 React 中使用 immutability-helper 设置可变对象键

java - 如何模拟 DriverManager.getConnection(...)?

java - 如何从 static void 方法返回 int 数据到 main 方法?

java - AspectJ 错误 : Could not find or load main class aop.

java - R 中的 Apache POI

java - DynamoDB 如何查询强一致性的非键属性?

variables - 为什么不可变变量可以作为参数传递给需要可变参数的函数?

java - Java 中字符串是如何创建和存储的?