衆所周知,在Java中final String中的值是一成不變的。你們都知道String的+(拼接)運算會丟棄內存引用並在內存中從新開拓地址,事實上也確實如此。但final的變量真的是一成不變的嗎?謹以此文打開程序員思路,跳出定式思惟,但願本文會給你的程序員生涯帶來新的思考。java
這個例子好久遠,早有前輩作過,但並非全部的程序員都接觸過。一般喜歡「獵奇」的程序員對此不會陌生。程序員
import java.lang.reflect.Field; public class ChangeFinalString { public static void main(String[] args) throws Exception { final String s = "12345: caiyongji"; System.out.println(s); System.out.println("hashcode: " + s.hashCode()); Field f = String.class.getDeclaredField("value"); f.setAccessible(true); char[] value = (char[]) f.get(s); value[0] = (char) 20851; value[1] = (char) 27880; value[2] = (char) 20844; value[3] = (char) 20247; value[4] = (char) 21495; System.out.println(s); System.out.println("hashcode: " + s.hashCode()); } }
例子中,經過final初始化一個String,而後反射獲取String類中名爲value的Field,並從新賦值value。執行後,你會發現String的hashcode值沒有變,String的值卻變了。另外,你還會發現這幾行簡單代碼的彩蛋。面試
看!是否是以爲常規能夠被打破,只要有足夠的技巧就能夠在編程中隨心所欲?也許有些嚴謹的程序員會指出hashcode方法的實現依賴於JVM,並不能直接反映內存的狀況。說實話,你甚至不須要記住本文的例子,我只是想打破你固有的思惟模式。shell
然而,上面的並非我想說的真正結論。編程
下面,纔是「聖誕版」真正的意義。框架
也許有些人會以爲收穫頗豐,我又掌握了一個面試問題的答案。沒錯,甚至像阿里、百度這樣的國內巨頭企業中,有一些面試官(注意是有一些),確實會問一些"final變量是不可變"這樣的silly question. 他們鑽研一門語言甚至知道全部具體實現的細節,甚至語言的bug。 但換個角度,在如此鑽研的同時,你是否考慮了你的時間成本、女友以及後代?!ide
做爲一個程序員,你是業務邏輯和代碼實現的接口。沒人在意你怎麼實現的業務,只在意你的代碼是否高效、準確、易用、易拓展(具體講,好比多少ms返回結果,參數結構是否簡單,是否容易添加新功能)。同理,你使用Java做爲你實現業務邏輯的工具,你更能夠選擇Python、Node.js、Kotlin甚至Linux shell腳本,那麼你是否要理解Java語言的全部實現?正如我在《如何成爲10倍速的程序員》中所說的不要記憶。工具
我是在號召你們不求甚解嗎?
是的。設計
若是把編程手段當成一種工具,無外乎語言、文檔、框架,這些均可以當成是工具的一部分。不要試圖用錘子打開螺絲釘,雖然你確實能夠作到。但這是反設計的。就像這個例子同樣,你能夠經過reflect改變final,但說白了,這種技巧並無什麼用,它會給你帶來不少麻煩,好比在拓展時、在java版本升級時考慮兼容性。code
因此,在使用一種「工具」時,要儘可能按照工具製造者的思惟模式進行使用,全部這些所謂的「技巧」都是在反設計。
最後,專一、嚴謹、邏輯清晰是一個程序員的品質,但在技術迭代如此迅速的大背景下,在代碼中追求極致是一我的類沒法作到的(若是用掌握技巧的多來衡量的話,你永遠沒法掌握全部技巧,而且,在技術迭代過程當中,你本來掌握的技巧也在逐步淘汰。),別忘了你生活中的朋友、家人和你的愛好。
過完聖誕就是新的一年,祝全部的程序員朋友聖誕快樂(本文寫於平安夜),同時在新的一年裏開啓程序員新的、不同的人生。