我正在尝试了解可变对象与不可变对象(immutable对象)。使用可变对象会受到很多负面影响(例如从方法返回字符串数组),但我很难理解这样做的负面影响。使用可变对象的最佳实践是什么?您应该尽可能避免它们吗?
最佳答案
嗯,这有几个方面。
没有引用标识的可变对象可能会在奇怪的时候导致错误。例如,考虑一个具有基于值的
equals
方法的Person
bean:Map<Person, String> map = ... Person p = new Person(); map.put(p, "Hey, there!"); p.setName("Daniel"); map.get(p); // => null
Person
实例在用作键时会在映射中“丢失”,因为它的hashCode
和相等性基于可变值。这些值在 map 之外发生了变化,所有散列都变得过时了。理论家喜欢在这一点上喋喋不休,但在实践中我并没有发现这是什么太大的问题。另一个方面是代码的逻辑“合理性”。这是一个很难定义的术语,涵盖了从可读性到流程的所有内容。一般来说,您应该能够查看一段代码并轻松理解它的作用。但比这更重要的是,您应该能够说服自己它所做的事情正确。当对象可以在不同的代码“域”之间独立更改时,有时很难跟踪内容、位置和原因(“spooky action at a distance”)。这是一个更难举例说明的概念,但在更大、更复杂的架构中经常会遇到这种情况。
最后,可变对象在并发情况下是 killer 。每当您从单独的线程访问可变对象时,您都必须处理锁定。这会降低吞吐量,并使代码显着更难以维护。一个足够复杂的系统会使这个问题变得不成比例,以至于几乎不可能维护(即使对于并发专家来说也是如此)。
不可变对象(immutable对象)(更具体地说,不可变集合)避免了所有这些问题。一旦你了解了它们的工作原理,你的代码就会变得更容易阅读、更容易维护,并且不太可能以奇怪和不可预测的方式失败。不可变对象(immutable对象)甚至更容易测试,这不仅是因为它们易于模拟,而且还因为它们倾向于强制执行的代码模式。简而言之,它们都是很好的实践!
话虽如此,我对这件事并不是一个狂热分子。当一切都是不可变的时,有些问题就无法很好地建模。但我确实认为您应该尝试将尽可能多的代码推向这个方向,当然假设您使用的语言使这一观点站得住脚(C/C++ 使这变得非常困难,Java 也是如此) 。简而言之:优势在某种程度上取决于您的问题,但我倾向于更喜欢不变性。
关于oop - 可变对象与不可变对象(immutable对象),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/214714/