必须是不可变对象的所有属性都是final?
据我说不.但我不知道,我是否正确.
我正在重新阅读Java Concurrency In Practice,我不确定我是否完全理解有关不可变性和安全发布的章节.
这本书的内容是:
任何线程都可以安全地使用不可变对象而无需额外的同步,即使不使用同步来发布它们也是如此.
我不明白的是,为什么有人(有兴趣使他的代码正确)不安全地发布一些参考?
如果对象是不可变的,并且它是不安全地发布的,我理解获得对该对象的引用的任何其他线程将看到其正确的状态,因为由适当的不变性提供的保证(使用final字段等).
但是如果发布是不安全的,那么另一个线程可能仍然会null在发布之后看到或者之前的引用,而不是对不可变对象的引用,这对我来说似乎是没有人愿意的.
如果使用安全发布来确保所有线程都能看到新引用,那么即使对象实际上是不可变的(没有final字段,但也无法将它们静音),那么一切都是安全的.正如书中所说:
安全发布的有效不可变对象可以被任何线程安全地使用而无需额外的同步.
那么,为什么不变性(与有效不变性相比)如此重要?在什么情况下需要不安全的出版物?
在给我的问题具体化之前,让我提供一些背景知识:我的主要编程语言是C++和Java.使用C++时,我发现应用const正确性很重要,即声明这样的函数:
A::DoSomething( const B& arg ); // guarantees that arg is not modified
A::DoSomething() const; // guarantees that the object of type A is not modified
A::DoSomething( const B& arg ) const; // both of the above
Run Code Online (Sandbox Code Playgroud)
事实上,我经常希望这const是默认值,并且必须以某种方式标记被修改的对象.
我使用的主要原因const是:
众所周知,Java没有const关键字(你不能做上面的事情final),这个事实在这里已经讨论过,例如参见:Java中的const(C++)的等价物.
通常提出的Java替代方法是使您的类不可变.虽然这不是完全替代,const因为它适用于每个类而不是每个使用类的上下文,但在大多数情况下它对我来说都可以正常工作.
但是不可变类有一个大问题:不可变性并不明显.要知道一个类是否真的是不可变的,据我所知,你基本上必须检查完整的源代码.任何方法都可以有一个后门,通过它可以修改对象.
那么有更简单的方法来检查不变性吗?或者是否有任何最佳实践以某种方式标记一个类是不可变的?
注意:我知道这两种语言都提供了绕过constness或immutability的"邪恶伎俩":C++ const_cast和Java都有反思.但是对于我的问题的背景,我们假设这些都没有被使用.
在Java Concurrency In Practice一书中,它解释了"有效不可变"对象与可变对象并发性的优点.但它没有解释"有效不可变"对象在真正不可变对象上提供的优势.
我不明白:在你决定安全地发布一个"有效不可变"的对象的那一刻,难道你不能总是构建一个真正不可变的对象吗?(而不是做你的"安全发布",你建立一个真正不可变的对象,就是这样)
当我正在设计类时,我无法看到我无法始终构建一个真正不可变对象的情况(如果需要使用委托等来构建其他包装对象,当然这些对象本身就是不可改变的)我此刻决定"安全地发布".
那么"有效不可变"的对象和他们的"安全出版物"只是一个糟糕的设计或糟糕的API的情况?
你会在哪里被迫使用一个有效的不可变对象,并被迫安全地发布它,你无法建立一个更优越的真正不可变对象?