作者回复: “引用传递”的理解可能误导了你。学习C语言和Java语言的时候,可以把赋值都看作值传递,然后去理解不同的类型传递的值到底是什么,也就是到底是什么值。
比如,这个例子的helloWordsMap和temporaryMap的两个变量,其实它们的值都是指向一个map的地址。map的变化,并不会引起指向这个map的地址的变化。所以,才会有让人迷惑的“引用传递”的说法。但是,helloWordsMap和temporaryMap这两个指向map地址变量,是可以变化的。而且,它们的变化都是独立的,不传递的。
第一次赋值,helloWordsMap和temporaryMap相同了,指向同一个地址。需要注意的是,但从变量本身看,helloWordsMap和temporaryMap是两个不同的变量,一个变量的变化,对另外一个变量没有影响。你可以仔细琢磨一下我说的值传递。
第一次赋值后,helloWordsMap可能指向null地址,然后temporaryMap就也有可能指向null。同步时,需要检查helloWordsMap是不是还是指向null。如果helloWordsMap已经不指向null了,temporaryMap依然是指向null的,这时候,就要更新temporaryMap的指向地址。所以,需要第二次赋值。
作者回复: 延迟分配和同步是两个概念,分开理解更容易些。 关于延迟分配,参见地二十四讲。 如果非要放一起的话: 延迟分配,有的时候可以免除同步,有的时候降低同步,有的时候没什么影响。你看,和不放一起没什么两样。更多的具体的例子,请参考《Effective Java》。
作者回复: 是的,这么复杂的延迟分配代码,要解决的就是helloWordsMap变化的同步问题。
作者回复: 一般采用延迟分配方法的代码,都很简单,而且变量仅赋值一次。其他的场合,还要看具体的代码。 比如final修饰的变量,就不会反复变化。