一年純手工打造的Java老A上冊開始預售了
Java老A這本書寫了很久昨天終於開始在china-pub、京東、天貓上開始預售了不過既然叫預售就肯定還沒到貨。
有興趣的人可以去看看哈後續其它網站地址也會在這裏公開
china-pub
https://search.china-pub.com/s/?key1=java%cc%d8%d6%d6%b1%f8&type=&pz=1
京東
https://search.jd.com/Search?keyword=Java%E7%89%B9%E7%A7%8D%E5%85%B5&enc=utf-8
天貓
https://list.tmall.com/search_product.htm?q=Java%CC%D8%D6%D6%B1%F8&type=p&vmarket=&spm=3.7396704.a2227oh.d100&from=mallfp..pc_1_searchbutton
關於本書內容請參考https://blog.csdn.net/xieyuooo/article/details/38373409
裏麵有本書的所有目錄信息封麵等。
關於寫這本書的初衷和曆史可參看
https://blog.csdn.net/xieyuooo/article/details/8915934
https://blog.csdn.net/xieyuooo/article/details/12493383
前期將手稿樣章貼了一個小節到博客可參考
https://blog.csdn.net/xieyuooo/article/details/17452383
開始預售我順便將前言、第一章部分內容貼出前言是寫給讀者朋友的大家可以參考下該書是否適合自己如下
本書書名為《Java特種兵》又名《Java老A》目的很簡單希望作為讀者朋友的你有一天能夠成為一個單兵作戰能力極度強悍的Java程序員。眾所周知Java程序員多如牛毛我希望學習本書的讀者有誌者事竟成、出類拔萃練就一身好本領成為Java界的特種兵。
關於本書
冰凍三尺非一日之寒本書不是什麼神功秘籍所以它無法讓你在短時間內從一個小鳥變成一個牛人更加無法讓你從牛人成為大師這本書是希望讀者朋友能夠在糾結的時候想起還可依賴它。因為本書不僅僅在講解一些知識同時也包含了作者以及作者同事的一些工作經曆以及工作經曆中的那些痛苦與糾結我們希望在這本書的陪伴下你在糾結之時選擇的不是放棄自我而是堅持到勝利的那一刻。
作者本人也不是什麼牛人更加不是絕頂高手隻能說我們經曆的某些事情也許值得去分享這些內容不僅僅包含一些知識同時也包含了很多思想、方法和麵對問題的態度注重功底和修為的提升。如果有一天你發現這本書帶給你更多的是方法從而讓你建立起自己的許多思路快速學習和成長那麼本書的一個重要目的就達到了如果有一天你發現再去看某些“牛人秘籍”會比以前輕鬆和愉悅那麼也許這本書有點小功勞。
本書不是什麼代碼大全也不是專門講解某些指定的知識板塊的書籍例如JVM並不會針對某些專門的知識板塊去做過細的說明也不會去說明詳細的API更加不會全麵地說明它們的源碼這是沒有意義的。通過本書希望你能從內心認識到“知識無涯”我們總會遇到自己沒有見過的問題需要學會的就是如何麵對這些問題即如何去思考和定位如何去學習和成長。
在本書中可能會以各種“換位思考”的方式來探討一些技術內容從技術本身的角度來講側重於講解技術之中蘊藏的各種奧秘以及探索奧秘的一些思路而不是講解一些技術的使用希望讀者在這個過程中開始有意識地去理解知識的應有深淺之分並同時真正掌握Java基礎提升自我的功底同時還能找到提升功底的方法。
本書中許多對話和探討的模式適合像小說一樣來靜心品味我相信如果你能靜心那麼不論是初學者還是有一定功底的人都能從本書中受益。作者本人在剛進入大學的時候是一個連計算機是什麼都不知道的人也曾經有過為了通過C語言考試而死記硬背代碼的經曆後來通過不斷努力才有能力寫出這本書。因此本書會結合當時胖哥從一個計算機屆的“文盲”開始成長的過程中所擁有的一些“可愛”的思想經曆如果你有類似的思想經曆希望這本書能夠幫助到你也同時希望你理解到隻要你願意你就一定行的
本書有的內容風格會偏於娛樂這些內容所描述的技術肯定不會那麼嚴謹由於不嚴謹可能會讓不同的讀者產生仁者見仁、智者見智的情況。對於某些有著同樣工作經曆的人看來也許會有著發自內心的共鳴對於初學者可以是一個大概的形象理解。雖然書中的許多解釋並不是技術點上的準確解釋但我不希望初學者“小夥伴們”僅僅注重娛樂本身的話題而要想想這種娛樂的例子所帶給自己的一些感性認識。
本書會談到一些成長性的內容因此我們可以先大概定位下一些不同層次的人會怎樣思考怎樣做事情讓大家有個形象上的認識。
Java學習三段位
許多初學者就像是無頭蒼蠅四處亂撞什麼都想學學了就丟而且喜歡鑽牛角尖甚至沒有獨立思考的習慣遇到問題問再解決問題。他們經常會問“為什麼我的東西在這好用在那不好用”因為你還根本不知道問題的原因當然不知道這麼多的為什麼了任何問題都需要定位分析再解決再總結。麵對問題要靜下心來通過自己對基礎的認識來分析可能的原因然後逐步縮小範圍再定位問題。如果拋一個錯誤就能知道原因那麼直接設計一個答題的機器就可以了而不需要任何人為的介入。
學到一定程度的人懂得思考懂得換位思考能解決大多實際問題他們不僅僅能開始自己定位問題而且開始具有“前瞻性”思考一些問題未來可能存在的潛在情況也開始逐步關注一些內在原理。不過可能是藝高人膽大這些人有可能會犯一些不該犯的錯誤他們通常是一些十分優秀的程序設計者很多時候可能是為了展現自己的技術能力會將一些不值得去做的事情不斷細化和優化或者去做一些別人做過的事情如果因為這樣丟掉主業務則通常說它是過度優化、過度設計、重複製造。作者本身也有同樣的親身經曆而很矛盾的在於是否真的是過度設計在不同的場景下會有不同的看法和評價因此這個階段的同學通常會有一個糾結期。在這個階段的人開始講究內外雙修也同樣是一個積土成山、積水成淵的過程因為有一定的功底學習很多知識都很快在知識麵上會有很大的突破在知識點上也會逐步加深可能在工作中不論是業務還是技術上都有了很多的選擇被認為是工作能力很強的人。一些很“牛”的開發人員就會開始意識到很多代碼如何去編寫會更優雅、更加高效用更簡單的代碼搞定更多的問題但還未上升到係統級別和架構級別。
可能更高級別的人開始具有很強的全局觀讓係統全局更加具有可維護性和伸縮性係統性能良好穩定性十足能搞定各類架構、部署、規範化等相關的問題在某些領域上也是說話很有分量的人物。他們可能會花很多時間去寫通用模型和設計將難題簡單化解決大家解決不了的難題。通常會盡量讓係統的維護變成一條配置或是幾條簡單代碼但是可以頂得上一群人寫一堆代碼這就是特種兵程序員的“快”、“準”、“狠”、“穩”。
這裏的各種級別僅僅是作者“自言自語”並不代表什麼要做到沒有級別在心中才能真正讓自己快速成長。另外看了這些級別並不代表今天我是初學者明天將不好的習慣改掉後就“脫胎換骨”了也並不代表自己在某件小事情上有了大師的風範就代表自己是大師了。這些東西都是經曆一些事情後才會形成一些自然意識我們隻是有意識地去學習他們為什麼會這樣做事情為什麼年輕人比老員工有活力但通常來講“薑還是老的辣”。
□ 適合對象
1有一定Java基礎並希望能在Java技術上有所成長的人。
本書學習有一定門檻如果是初學者則可以先以書中的一些例子為引導希望了解為什麼的時候再來看其中的解釋。
2對於能靜心看書的初學者可以迭代著看本書。
雖然有一定門檻不過初學者隻要能靜心迭代著讀幾次後你或許也能體會出裏麵有很多思想、方法、解決問題的手段、看問題的側麵甚至麵對問題的心態那麼也可以受益良多。
3本書是一個載體一個推崇自我修為、內外雙修的載體修行看個人所以適合於想要以自我提升為主要目的的讀者。
4工作一段時間對知識和發展的方向很迷茫甚至對某些觀念也比較迷茫但是又渴望去解決這些問題渴望自己成長渴望自己能找到道路的人。
□ 不適合對象
1Java方麵的高手和牛人因為這本書並不能助你從牛人變成大師。
2做客戶端如Android或嵌入式的Java程序員因為書中大多內容是以服務器端Java來講解的極少考慮客戶端的問題。
3如果你對自己或周圍的一切很絕望看到的所有東西都是邪惡、虛偽的也沒有想過要讓自己進步。
4希望這本書成為技術字典的同學不適合讀因為這本書不是代碼大全也不是知識點精準解釋的匯聚更不是API的列表。
5希望係統性學習某些專業知識的同學不適合看本書因為本書講解的是一種“碎片化”學習方式或者說是以一些小例子為基礎進一步處理相關問題的方式。
作為書籍的作者希望讀者能夠快樂地學習到知識每天空餘時間看看而不是一種壓力麵對技術擁有獨自思考問題的能力而並非掌握某種技術本身通過輕鬆地接觸很多知識並且能有所體會不斷地去總結、抽象能得出自己的分析問題、解決問題的方法磨練出超越普通程序員的功底最終成為Java老A。
本書其實是一本Java的野書、雜談會盡量用通俗易懂的方式來講解一些複雜的問題和技術。不過這畢竟不是一本娛樂的書某些內容胖哥還是會說得比較嚴謹。書中除了講解一些“功底類”的技術外大部分技術不會講得太深大多隻是拋磚引玉給你一個思路當你需要去接觸更深的技術的時候在這本書中可能會有一個較為形象的例子供你參考也許就大概知道了如何去理解。若功底夠好就會發現萬變不離其宗一切都可以歸於基礎而且大多複雜的思路都源自於生活的靈感。
如果是初學者希望你不要期望每天看太多內容而是希望你看了後盡量去思考不用完全看懂每天能夠有一個心得當你在實踐中遇到某些問題開始擁有靈感時本書或許會印證這一切。
本書提到的技術僅僅是一個引導、一種探討、一種思路在闡述一件事情好與不好的時候通常會以多種角度去看待問題的不同側麵再來說明為什麼會有這樣的經驗同時也可能會探討這些經驗是否能夠受用終身。因為技術的時代在不斷革命現在的技術十分泛濫但都殊途同歸我們要跟上時代又要歸納總結也許很多時候我們沒有精力去學習所有的知識但有精力讓自己提升學習能力從而來學習更多的東西也有精力來探索工作領域內的知識奧秘而前提是應當有探索奧秘的習慣以及足夠的功底。
本書的目的在於個人成長極少談到關於團隊合作與規範化等方麵的知識當然作為一個單兵作戰能力極強的人應當有這方麵的意識和思維即使本書中沒有提及大家也應當去掌握。同時也請讀者朋友注意本書所提倡的單兵作戰能力並不是期望大家去做一個技術上的孤獨者而是更好地去工作。
□本書將采用HotspotVM 1.6作為講解的例子可通過命令“java –version”得到JVM版本而測試的例子如果是在具體的OS環境下測試則會單獨說明。書中也會提到JDK 1.7的內容相應的代碼如果要運行也要選擇JDK 1.7。
□本書中“部分例子”必須采用-server模式來運行和模擬尤其是第5章並發編程中的許多例子在例子中通常會有專門的備注和說明請讀者注意參看。
□篇幅所限本書中的例子大多隻是片段以說明實際的問題為主需要完整的例子請參看配書光盤中的相關demo信息書中的例子都有與之對應的實際代碼除十分複雜的代碼外從demo中獲取的代碼進行相關的配置後均可直接在對應平台上按照指定結果運行。
□本書的代碼分源碼和代碼兩種源碼為第三方源碼可以到官方網站下載參看書中會介紹源碼的版本和思路並貼出部分關鍵源碼的功能和設計思路。
□本書從第2篇開始每一篇都會有“致讀者言”目的是讓讀者更好地了解這部分內容應該從何種角度去理解它會說些什麼會給你帶來什麼你為什麼需要這些。
□網絡上大家都稱作者為“小胖哥”或“胖哥”所以在本書中也會以這兩個稱唿作為作者本人的代名詞。
本書分上下冊總共5篇上冊兩篇內容分別是功底篇和源碼篇強調個人修為的提升也是本書主旨所在希望能幫助各位讀者朋友提升“功力”下冊中將基於上冊的內容融入設計、實現的細節。
上冊
第1篇 Java功底篇
建議所有本書的讀者朋友都讀下本篇的內容所謂“練武不練功到老一場空”你是否要成為一個老A級程序員功底的提升是十分重要的通過對第1篇的學習希望讀者能知道如何驗證自己的功底如何提升自己的功底而能提升多少完全要靠你自己的屬性哦
第1章從簡單的角度來驗證功底通過一些簡單的例子來說明我們應當如何去掌握Java的基礎同時也包含一個“老A級程序員”除功底外還需要有麵對逆境的心態。
第2章和第3章分別介紹關於計算機的工作原理和Java虛擬機的基礎知識。胖哥認為一個優秀的Java程序員應當知道自己的程序在計算機內部是如何運行的更需要知道虛擬機是如何運行的效率對比怎樣此好比“習武之人需要知道何為武學”。
第4章講解Java通信在了解了運行基本原理後你應當了解很多網絡交互已經被Java的框架包裝得不再像通信程序了就像是“被裝修後的房子你不再知道房屋本身是用什麼建造的”。但如果你是老A就應當知道這些這樣才能知道遇到各種怪異的問題時如何去解決你會發現“一切源自基礎偶然問題隱藏必然”。
第5章講解Java並發如果讀者朋友確實遇不到則可以跳過但要成為Java的老A這應該算是基礎知識老A應該知道Java並發是怎麼樣的。除了客戶端程序及單片機等Java並發程序處理其實無處不在就好比“一個城市的交通很多的車輛需要通信應當如何調度來提高流量避免交通事故”。
第6章講解數據庫知識大部分程序員都應該使用過數據庫、文件通過學習第4章通信方麵的內容應該會有一些概念但是麵對存儲你是否想要了解一些內在了解一個程序員所需要知道的內在這樣可能會使得你的工作更加得心應手。說了這麼多你是否發覺學習Java為何要了解如此多的東西是的你需要知道“多個門派的武學麵對不同的思想碰撞來切磋才會有更多的體會”。作為一個老A才會擁有單兵作戰能力極強的作戰素質。
第2篇 源碼篇
達到一定程度的程序員一般會開始對實現本身感興趣想了解為什麼了解別人是如何設計和實現的。
起初在麵對框架的時候可能會去猜測或測試它是如何實現的但逐漸發現猜測和測試並不那麼靠譜因為版本和環境影響因素太大我們開始想要知道一些內在看源碼成為一個必然。源碼麵前沒有秘密可言看過源碼你會對問題定位和編寫代碼擁有自信開始對技術本身有量化的認識。
本篇並不是網絡天下源碼也不會對某種源碼做全麵講解而是通過閱讀源碼來說明我們應當如何閱讀源碼。
在本篇開始部分會先介紹為何要閱讀源碼講解哪些源碼如何閱讀源碼請有疑問的小夥伴們關注一下哦。
第7章講解源碼基礎說明Java常見的框架基礎知識主要包括反射、AOP、ORM、Annotation和配置文件的原理。在這裏不僅僅會闡述技術本身同時也會聯係一些實際框架的可能實現方法。老A一定要“知其然知其所以然”。
第8章和第9章分別講解JDBC、Spring的源碼這裏不會說明這些三方包的所有源碼和關鍵點。但通過幾種不同類型的框架源碼希望讀者能體會源碼之中的“思維方式、設計、架構”以及了解到不同源碼的區別所在。雖然區別很多但如果你有一些“百川納海、源自同門”的感受那麼小夥伴們就成長了很多。
第10章是對第2篇的知識總結在閱讀源碼後不是讀完就完了而是應當有所體會。通過對源碼基礎知識的初步了解和對一些源碼的閱讀我們逐步有能力在接觸一個自己從未見到的框架時可以大概知道它的大致內在並且大多數情況下可以輕鬆搞定它即使有一定難度也會從根本的角度去看待這些技術問題進一步快速地通過看它的代碼了解內在而不會被浮於表麵的使用所迷惑。這就好比雖然魔術師的表演眼花繚亂但是在他們同行眼中都是知根見底的因為我們也是專業的所以不應當被一些東西所迷惑。
下冊
第3篇 設計篇
老A雖然不像軍師那樣“運籌帷幄之中決勝千裏之外”但也同樣需要有全局的部署思想對臨場應變以及撤退方案和路徑要有全局把控能“在萬軍之中取上將首級”使用最低犧牲得到最高的成果。
在設計篇中胖哥希望給你帶來的不僅僅是現有老A的技術也包含了他們的許多思想。既然是思想自然是結合場景最佳它需要融入老A的智慧不限於表達的形式因為這些形式隻是一種思想傳承的載體。
第1章中胖哥會用平時工作中的例子說明一些常用的設計模式但並不會將Java所有的設計模式全部詳細講解因為這不是本書的主旨而且那樣並沒有多大意義。在實際的應用中場景是非常重要的變化遠遠大於這些設計模式本身所提供的“招式”。模式本身提供一種建議性的設計方法就好比武學中的“招式是死的人是活的”不同年齡段修煉同樣的武學與不同的對手較量不論是招式的順序還是臨場的動作都會有很大的變化。如果在實戰對決中一再用套路來較量就會被套路牽引著走也會被對手打亂節奏而套路本身給我們提供了一種處理場景的方法靈活應用才能用以實戰這樣才能達到“無招勝有招”的境界。
第2章和第3章介紹兩個實例的設計它們是兩種完全不同類型的程序在這個過程中嚐試應用設計模式中的一些知識和思路也就是需要知道如何利用招式來對敵。但大家不要僅僅局限於這兩章所給出的例子因為實際場景可以千變萬化針對自己所遇到的場景需要去揣摩和思考。我們的例子通常不會寫到實現部分到設計部分基本結束希望你能理解到“思想和方法應當源於生活和自然”。
第4篇 實現篇
在原計劃中胖哥並沒有打算寫關於“實現”方麵的內容不過胖哥發現在實際工作中小白“童鞋”們所麵對的可能最多是實現於是增加了這部分內容。但是在實現篇並不是拿一個業務實例來寫代碼談什麼呢
第4章談談項目中各種工作人的交互、開發模式、心態、技術上的思維方式、一些優化思路。第5章簡單談談UI的一些用途、繁雜的點在那裏。第6章談談實際工作中經常會遇到的“坑”這些坑不容易被發現但是我們經常容易掉進去希望大家知道的不僅僅是這些坑而是通過這些坑了解到眾多技術都是一把“雙刃劍有好處必有壞處”隻有最佳的場景選擇最合適的技術學會如何去量化與選擇同時需要了解到現在的工作對個人素質的要求越來越高。
第5篇 擴展篇之論道
擴展篇為雜談也是論道篇讀者可以先看第5篇的內容本篇是對知識麵和思想的一個擴展。一個老A應當知道業界的一些技術所謂“知己知彼百戰百勝”接觸任何一種問題都要有相應的解決方案。
第7章和第8章以走馬觀花的方式來介紹一些集群知識、分布式知識但並不意味著實際的技術和走馬觀花那樣簡單。作為老A程序員胖哥認為需要知道這些這樣才能更好地做好一些事情或者說有機會去做更有挑戰的事情。也許你今天用不到這些但當你用到時便能更加得心應手。
第9章講解技術量化與權衡的一些事情會談一些時間管理、團隊合作、過度優化、預知問題、不同項目的實現思路等。這裏闡述的中心思想是我們應當在技術追求的道路上考慮各種成本與價值的問題從個人做起再看看團隊協作。
第10章是完結章主要是探討一些心態以及勵誌有興趣的小夥伴們可以看看沒有興趣的無須關注本章。現代老A除了素質過硬外更要擁有智慧智慧包含了豐富的知識麵同時也包含了對於世界的理解靜心做好當下有機會去做好創新在芸芸眾生之中脫穎而出。
上麵部分為前言的主要部分下麵貼一點點第一章的小內容大家可以參考下是否適合自己的口味
1.1 String的例子見證下我們的功底
哇塞第1節就開始講代碼例子受不了啦胖哥你壞死了所有的書第1節都是寫這個領域有什麼東西的。
哈哈小胖哥天生就是個逆天之人哦希望你能先實踐有了感性認識後再進行理論了解內在。
下麵的代碼改編於網絡牛人的一段程序先看代碼清單1-1。
代碼清單1-1 一段String的比較程序
private static void test1() {
String a = "a" + "b" +1;
String b = "ab1";
System.out.println(a == b);
}
胖哥你是不是考我智商呀我們平時對比兩個對象不是用equals()嗎老師告訴我兩個字符串用等號是匹配不了的結果應該是false吧。那麼結果到底是多少呢
運行結果
true
什麼竟然是true為什麼是true這是要逆天嗎這小段程序徹底顛覆了我的經驗和老師教我的真理“我和我的小夥伴們驚呆了……”
胖哥告訴你這不能怪老師老師帶進門修行靠個人
也許有朋友做出了true或猜出了true那麼可否知道原因呢如果你知道那麼本節跳過無須再看如果還不知道就聽聽胖哥給你說說他所理解的原因。
要理解這個問題你需要了解些什麼
◎關於“==”是做什麼的
◎ equals呢
◎ a和b在內存中是什麼樣的
◎編譯時優化方案。
下麵的內容會很多現在我們可以站起來簡單運動一下端一杯咖啡慢慢解讀下麵的內容。
1.1.1 關於“==”
首先要知道“==”用於匹配內存單元上的內容其實就是一個數字計算機內部也隻有數字而在Java語言中當“==”匹配的時候其實就是對比兩個內存單元的內容是否一樣。
如果是原始類型byte、boolean、short、char、int、long、float、double就是直接比較它們的值。這個大家應該都清楚這裏不再詳談。
如果是引用Reference比較的就是引用的值“引用的值”可以被認為是對象的邏輯地址。如果兩個引用發生“==”操作就是比較相應的兩個對象的地址值是否一樣。換一句話說如果兩個引用所保存的對象是同一個對象則返回true否則返回false如果引用指向的是null其實這也是一個JVM賦予給它的某個指定的值。
理解寓意大家各自拿到了一個公司的offer現在我們看看哪些人拿到的offer是同一個公司的。
1.1.2 關於“equals()”
equals()方法首先是在Object類中被定義的它的定義中就是使用“==”方式來匹配的這一點大家可以參看Object類的源碼。也就是說如果不去重寫equals()方法並且對應的類其父類列表中都沒有重寫過equals()方法那麼默認的equals()操作就是對比對象的地址。
equals()方法之所以存在是希望子類去重寫這個方法實現對比值的功能類似的String就自己實現了equals()方法。為什麼要自己去實現呢因為兩個對象隻要根據具體業務的關鍵屬性值來對比確定它們是否是“一致的或相似的”返回true|false即可。
迷惑1equals()不就是對比值的嗎為何說相似
答曰一日偶遇怪俠“蝸牛大師”一枚賜予神劍於數人獵人將其用於打獵農夫將它用於劈材將軍用它保家衛國俠客用它行俠仗義、懲奸除惡等等。
例如在對比一些工程的圖紙尺寸的時候由於尺寸都會存在細節誤差可以認為寬度和高度比較接近就可以返回true而不一定非要精確匹配。另外圖紙紙張的屬性除了長度、寬度外還有如名稱、存放位置、卷號等屬性但是我們可能隻需要對比它的長度與寬度在這個範圍內其餘的屬性不會考慮。也就是說兩個對象的值是否相同是自己的業務決定的而不是Java語言來決定的。
感悟變通讓標準變為價值給你一種思想和標準你可以有不同的使用不能死扣定理我們要解決問題
迷惑2equals()重寫後一般會重寫hashCode()方法嗎
要說明這個問題我們先要補充一些概念。
Java中的hashCode是什麼——hashCode()方法提供了對象的hashCode值它與equals()一樣在Object類中提供不過它是一個native本地方法它的返回值默認與System.identityHashCode(object)一致。在通常情況下這個值是對象頭部的一部分二進製位組成的數字這個數字具有一定的標識對象的意義存在但絕不等價於地址。
hashCode的作用——它為了產生一個可以標識對象的數字不論如何複雜的一個對象都可以用一個數字來標識。為什麼需要用一個數字來標識對象呢因為想將對象用在算法中如果不這樣許多算法還得自己去組裝數字因為算法的基礎是建立在數字基礎之上的。那麼對象如何用在算法中呢
例如在HashMap、HashSet等類似的集合類中如果用某個對象本身作為Key也就是要基於這個對象實現Hash的寫入和查找那麼對象本身如何能實現這個呢就是基於這樣一個數字來完成的隻有數字才能真正完成計算和對比操作。
hashCode隻能說是標識對象因此在Hash算法中可以將對象相對離散開這樣就可以在查找數據的時候根據這個key快速地縮小數據的範圍。但不能說hashCode值一定是唯一的所以在Hash算法中定位到具體的鏈表後需要進一步循環鏈表然後通過equals()來對比Key的值是否是一樣的。這時hashCode()與equals()似乎就成為“天生一對”。換句話說一個是為了算法快速定位數據而存在的一個是為了對比真實值而存在的。
與equasls()類似hashCode()方法也可以重寫重寫後的方法將會決定它在Hash相關數據結構中的分布情況所以這個返回值最好是能夠將對象相對離散的數據。如果發生一個極端的情況即hashCode()始終返回一個值那麼它們將存在於HashMap的同一個鏈表中將會比鏈表查詢本身還要慢。
在JDK 1.7中Hash相關的集合類對使用String作為Key的情況不再使用hashCode方式而是有了一個hash32屬性其餘的類型保持不變。
換個思路hashCode()與equals()並不是必須強製在一起如果不需要用到這樣的算法也未必要重寫對應的方法完全由你自己決定沒有語法上強製的規約。
寓意此好比寶劍是否需要有劍鞘寶貝是否需要有寶箱雄性是否必須需要雌性地球是否需要有月亮
而並非是樹是否需要土壤生命是否需要食物魚兒是否必須需要水世界是否需要陽光
感悟一切在於場景與需求十分需要但也可以在某些情況下放棄。
有人說對比兩個對象是否一致可以先對比hashCode值再對比equals()。
這似乎聽上去挺有道理的但是胖哥本人可並不這麼認為為什麼呢胖哥認為hashCode值根本不是為了對比兩個對象是否一致而存在的可以說它與兩個對象是否一致“一點關係都沒有”。
假如你希望對比兩個對象是否是同一個對象則完全可以直接用“==”來對比而不需要用hashCode()因為直接對比地址值說明兩個對象是否為同一個對象才是最靠譜的。另外默認的hashCode()方法還會發起native調用並且兩個對象都會分別發起native調用native調用的開銷也是不小的。
假如不是對比地址而是對比值自然就需要對象中的某些屬性來對比。拿String類型的對象來講如果調用某個String對象的hashCode()方法它至少會在第1次調用這個方法時遍曆所有char[]數組相關元素來計算hashCode值這裏之所以說至少是因為這個String如果並發調用hashCode()方法則可能被遍曆多次遍曆過程中還需要外加一些運算。如果對比的兩個對象分別獲取hashCode自然兩個String對象都會分別遍曆一次char[]數組。
即使hashCode一樣了也同樣證明不了這兩個String是一樣的這個hashCode是根據char[]數組的值算出來的不同的String完全可以算出一樣的值還得再次循環兩個String中所有的字符來對比一次才能證明兩個對象是一樣的。其實遍曆了兩個char[]數組已經是最壞的情況了equals()還未必會這樣做在後文的圖1-2中會詳細說明。
換一個角度來講如果是兩個其它的自定義類型的對象不是String類型的對象之間判定出來hashCode不一樣也不能說它們的值不一樣有可能equals()匹配的是一個綜合值與hashCode一點關係都沒有還是要進行equals()這樣繞來繞去往往是把簡單問題複雜化了。
equals()內部要怎麼做就去怎麼做嘛想要優化完全可以像JDK自帶的許多類那樣先對比一些簡單的屬性值再對比複雜的屬性值或者先對比業務上最快能區分對象的值再對比其它的值或者先對比地址、長度等處理方式將那些不匹配的情況盡快排出。
有人說重寫後的hashCode()內部操作確實比equals()簡單許多倍其實這個動作判定也是可以放在equals()方法的第1步中來完成的無需外部程序關注。
補充String的equals()方法中默認就要先對比傳入的對象與當前的this是不是同一個對象。在HashMap等集合類的查找過程中也不是單純的equals()也會先對比兩個對象是不是同一個對象。
好累休息休息左三圈、右三圈再來看看胖哥為你做解讀
a和b的內存情況是什麼樣的
回到“代碼清單1-1”的例子中其中的等號說明a和b是指向同一塊內存空間的就像兩個人拿到同一個公司的Offer一樣他們像什麼呢見圖1-1“死冤家又在一起了”
圖1-1 兩個冤家又拿到同一個公司的Offer
為什麼a、b兩個引用都引用到同一塊空間了呢請看1.1.3節的內容解釋不過在這一節中我們先感性認識下JVM的一些“東東”在第3章中會有更詳細的介紹。小夥伴們不要著急我們一步一步來學習。
1.1.3 編譯時優化方案
a引用是直接賦值的b引用是通過“+”賦值的a和b兩個引用為什麼會指向同一個內存單元這就是JVM的“編譯時優化”。如此神奇小夥伴們驚呆了吧
當編譯器在編譯代碼String a ="a" + "b" + 1;時會將其編譯為Stringa = "ab1";。
為何因為都是“常量”編譯器認為這3個常量疊加會得到固定的值無須運行時再進行計算所以就會這樣優化。
疑惑編譯器為何要做此優化
寓意“小胖”說我的報銷單寫好了並蓋章了“小明”說我的也OK了那麼就合並一起郵寄報銷單吧。“小銳”說我的快寫好了不過還沒蓋章那你寫好後再說吧。
寓意為提升整體工作效率和節約資源能提前做的事情就提前做。我們自己設計一種平台或語言的時候是否會考慮這些呢
補充編譯器類似的優化還有許多在後文中會有介紹例如當程序中出現int i = 3 * 4 + 120時並不是在實際運行時再計算i的值而是在編譯時直接變成了i= 132。
容易出錯JVM隻會優化它可以幫你優化的部分它並不是對所有的內容都可以優化。例如就拿上麵疊加字符串的例子來說如果幾個字符串疊加中出現了“變量”即在編譯時還不確定具體的值是多少那麼JVM是不會去做這樣的編譯時合並的。而JVM具體會做什麼樣的優化不做什麼樣的優化需要我們不斷去學習才能把工作做得更好。
同理證明的道理String的“+”操作並不一定比StringBuilder.append()慢如果是編譯時合並就會更快因為在運行時是直接獲取的根本不需要再去運算。同理千萬不要堅定地認為什麼方式快、什麼方式慢一定要講究場景。而為什麼在很多例子中StringBuilder. append()比String的“+”操作快呢在後文中胖哥會繼續介紹原因。
====>篇幅所限就貼這些吧。
PS
如果一些小夥伴在試讀樣章、前言後感覺本書真的很適合自己但是個人經濟方麵存在壓力例如還在待業找工作、學生之類那麼可以聯係小胖小胖可以掏錢買這本書送給相應的小夥伴這方麵不要覺得不好意思為求知沒什麼大不了的小胖覺得如果自己的書能幫助到別人內心也會很開心的到目前小胖也送書給不少有類似需求的小夥伴了
最後更新:2017-04-03 05:39:56