@xuemingdeng
2017-02-15T11:01:46.000000Z
字数 1992
阅读 550
我是一个老Java人,从来没有对可变性问题有过太多的想法。Java不像其它语言,它没有确切的机制可以用于控制可变性和不可变性。我从来没有听说过Java对象有这样的特性。相反,我总是听到有人这么说它:“那个Java类没有setter方法”或者“那个Java类的值初始化之后就不能被修改”。这些都是对Java不可变性非正式的描述。可变性是命令式语言的默认行为,但我们从来没有仔细想过这一点。我们学习了这种编程范式,它们就进入到了我们的潜意识里。
在我的整个职业生涯中,我见过很多编程语言,它们对类的可变性区分得非常清楚。这个看起来很酷,不过我很少会用到它们(我的大部分工作是关于Android和J2EE),所以就这么过去了。它们不在我的影响力范围之内。
一年前,我开始使用Kotlin。它给我的开发工作注入了一股清流,如果有可能,我会尽量使用它来开发(我参与了Kotlin Weekly,如果有兴趣可以订阅它)。如果让你来做Android开发,你可能会选择Java。Java 1.0版本发布于1995年,也就是22年前。那时候的世界是另外一番景象,Java被设计用于解决当时存在的一些问题。那个时候还没有智能手机,普通手机也不像今天这样有这么多功能。在Java发布的时候,Windows 95都还没有公开发布(它跟Java一样老),eBay才刚刚成立。
我喜欢拿IT行业同股票市场作类比。在60年代,通用汽车是当时的巨无霸,没有哪个公司能够与之竞争。美国政府甚至想过要强行将通用公司拆分成几个小公司,避免它的垄断。而在今天,通用汽车犹如行尸走肉,在一次大型的救市之后幸存下来。在90年代,没有人想到Apple会在今天成为最大的全球化公司。
今日之星或将于明日陨落,而今日之停船或将于明日启航。
—— J.L. Collins《财富之路》
Java经历了很多的更新。我不只是在谈论Java,实际上我以Java为生,尽管并不仅限于Java。不过还有众多新星在升起,比如Kotlin。Kotlin提供了开箱即用的可变集合和不可变的集合。
最近,我的同事Mike Nakhimovich在Twitter上写道:
“把所有的东西都变成不可变的来避免可变性?”
这句话引起了我的思考。最近我发表了一篇博文“合理使用volatile和synchronized”,我意识到多线程和同步问题真的很复杂。它们有太多的边界情况,太多的概念,太多的抽象。而这个居然是开箱即用的解决方案。我偶尔会用到它们,不过我觉得它们更像是骇客行为。
现在让我们进入Java的可变性世界。为了简单起见,我们先对不可变性进行定义:
不可变类被创建之后,其状态就不能被更改。
这看起来很简单。如果你也是个Java开发者,或许现在就知道该怎样创建一个不可变的类:
我们已经讲解了理论部分,接下来我们可以做点什么呢?
好的方面
不好的方面
我该作何选择?
有人说“可变性是万恶之源”。我喜欢有更多的选择,不想让任何事物成为教条。Joshua Bloch在《Effective Java》里写道:
“类应该是不可变的,除非有充分的理由让它变为可变的。如果一个类不能被定义为不可变的,那么也要尽可能限制它的可变性。”
不可变性能够解决很多问题,也会让事情变简单,特别是在并发环境里。不过如果把不可变作为默认行为,反而会带来复杂性。所以,在决定使用可变性还是不可变性时,要根据实际情况选择最合适的方案。
本文已获得原作者翻译授权,查看原文:Learning to use and abuse Mutability