我正在尝试了解可变对象与不可变对象。使用可变对象会受到很多负面影响(例如从方法返回字符串数组),但我很难理解这样做的负面影响。使用可变对象的最佳实践是什么?您应该尽可能避免它们吗?
嗯,这有几个方面。
-
没有引用标识的可变对象可能会在奇怪的时候导致错误。例如,考虑一个Person
具有基于值的beanequals
method:
Map<Person, String> map = ...
Person p = new Person();
map.put(p, "Hey, there!");
p.setName("Daniel");
map.get(p); // => null
The Person
当用作键时,实例会在映射中“丢失”,因为它hashCode
平等是基于可变的价值观。这些值在地图之外发生了变化,所有散列都变得过时了。理论家喜欢在这一点上喋喋不休,但在实践中我并没有发现这是什么太大的问题。
另一方面是代码的逻辑“合理性”。这是一个很难定义的术语,涵盖了从可读性到流程的所有内容。一般来说,您应该能够查看一段代码并轻松理解它的作用。但更重要的是,你应该能够说服自己它的作用正确地。当对象可以在不同的代码“域”之间独立更改时,有时很难跟踪什么在哪里以及为什么(“远处的怪异动作 https://en.wikipedia.org/wiki/Action_at_a_distance_%28computer_programming%29”)。这是一个更难以举例说明的概念,但它是在更大、更复杂的架构中经常面临的问题。
最后,可变对象是killer在并发情况下。每当您从单独的线程访问可变对象时,您都必须处理锁定。这会降低吞吐量并使您的代码戏剧性地更难维护。一个足够复杂的系统会使这个问题变得过分严重,以至于几乎不可能维护(即使对于并发专家来说也是如此)。
不可变对象(更具体地说,不可变集合)避免了所有这些问题。一旦你了解了它们的工作原理,你的代码就会变得更容易阅读、更容易维护,并且不太可能以奇怪和不可预测的方式失败。不可变对象甚至更容易测试,这不仅是因为它们易于模拟,而且还因为它们倾向于强制执行的代码模式。简而言之,它们都是很好的练习!
话虽如此,我对这件事并不是一个狂热分子。当一切都是不可变的时,有些问题就无法很好地建模。但我确实认为您应该尝试将尽可能多的代码推向这个方向,当然假设您使用的语言使这一观点站得住脚(C/C++ 使这变得非常困难,Java 也是如此) 。简而言之:优点在某种程度上取决于您的问题,但我倾向于更喜欢不变性。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)