Java老A这本书是写了很长的时间,昨天终于开始china-pub、京东、活动当天发售的猫,现在,简称买卖,他当然还没有到。
有兴趣的人能够去看看哈(兴许其它站点地址也会在这里公开):
china-pub:
http://search.china-pub.com/s/?key1=java%cc%d8%d6%d6%b1%f8&type=&pz=1
京东:
http://search.jd.com/Search?keyword=Java%E7%89%B9%E7%A7%8D%E5%85%B5&enc=utf-8
天猫:
http://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
关于本书内容,请參考:
里面有本书的全部文件夹信息,封面等。
关于写这本书的初衷和历史可參看:
前期将手稿样章贴了一个小节到博客,可參考:
開始预售。我顺便将前言、第一章部分内容贴出。前言是写给读者朋友的,大家能够參考下该书是否适合自己。例如以下:
特种兵》。又名《Java老A》。目的非常easy,希望作为读者朋友的你,有一天能够成为一个单兵作战能力极度强悍的Java程序猿。众所周知。Java程序猿多如牛毛。我希望学习本书的读者有志者事竟成、出类拔萃,练就一身好本领。成为Java界的特种兵。
关于本书
冰冻三尺,非一日之寒,本书不是什么神功秘籍,所以它无法让你在短时间内从一个小鸟变成一个牛人,更加无法让你从牛人成为大师,这本书是希望读者朋友能够在纠结的时候想起还可依赖它。
由于本书不仅仅在解说一些知识,同一时候也包括了作者以及作者同事的一些工作经历,以及工作经历中的那些痛苦与纠结。我们希望在这本书的陪伴下,你在纠结之时选择的不是放弃自我。而是坚持到胜利的那一刻。
作者本人也不是什么牛人,更加不是绝顶高手。仅仅能说我们经历的某些事情或许值得去分享,这些内容不仅仅包括一些知识,同一时候也包括了非常多思想、方法和面对问题的态度,注重功底和修为的提升。假设有一天你发现这本书带给你很多其它的是方法。从而让你建立起自己的很多思路高速学习和成长,那么本书的一个重要目的就达到了;假设有一天你发现再去看某些“牛人秘籍”会比以前轻松和愉悦,那么或许这本书有点小功劳。
本书不是什么代码大全。也不是专门解说某些指定的知识板块的书籍(比如JVM),并不会针对某些专门的知识板块去做过细的说明,也不会去说明详细的API,更加不会全面地说明它们的源代码,这是没有意义的。通过本书,希望你能从内心认识到“知识无涯”。我们总会遇到自己没有见过的问题,须要学会的就是怎样面对这些问题,即怎样去思考和定位。怎样去学习和成长。
在本书中,可能会以各种“换位思考”的方式来探讨一些技术内容。从技术本身的角度来讲。側重于解说技术之中蕴藏的各种奥秘以及探索奥秘的一些思路,而不是解说一些技术的使用。希望读者在这个过程中開始有意识地去理解知识的应有深浅之分,并同一时候真正掌握Java基础,提升自我的功底,同一时候还能找到提升功底的方法。
本书中很多对话和探讨的模式,适合像小说一样来静心品味。我相信假设你能静心,那么不论是刚開始学习的人还是有一定功底的人,都能从本书中受益。作者本人在刚进入大学的时候。是一个连计算机是什么都不知道的人,也以前有过为了通过C语言考试而死记硬背代码的经历,后来通过不断努力,才有能力写出这本书。因此,本书会结合当时胖哥从一个计算机届的“文盲”開始成长的过程中所拥有的一些“可爱”的思想经历,假设你有相似的思想经历,希望这本书能够帮助到你,也同一时候希望你理解到:仅仅要你愿意,你就一定行的!
本书有的内容风格会偏于娱乐,这些内容所描写叙述的技术肯定不会那么严谨,由于不严谨,可能会让不同的读者产生仁者见仁、智者见智的情况。对于某些有着相同工作经历的人看来,或许会有着发自内心的共鸣。对于刚開始学习的人能够是一个大概的形象理解。尽管书中的很多解释并非技术点上的准确解释,但我不希望刚開始学习的人“小伙伴们”仅仅注重娱乐本身的话题,而要想想这种娱乐的样例所带给自己的一些感性认识。
本书会谈到一些成长性的内容。因此我们能够先大概定位下一些不同层次的人会怎样思考,怎样做事情,让大家有个形象上的认识。
Java学习三段位
很多刚開始学习的人,就像是无头苍蝇,四处乱撞,什么都想学,学了就丢,并且喜欢钻牛角尖,甚至没有独立思考的习惯。遇到问题问,再解决这个问题。
他们常常会问:“为什么我的东西在这好用,在那不好用?”由于你还根本不知道问题的解决办法,当然不知道这么多的为什么了,不论什么问题都须要定位分析,再解决。再总结。面对问题要静下心来通过自己对基础的认识来分析可能的原因,然后逐步缩小范围。再定位问题。假设抛一个错误就能知道原因,那么直接设计一个答题的机器就能够了,而不须要不论什么人为的介入。
学到一定程度的人,懂得思考,懂得换位思考。能解决大多实际问题,他们不仅仅能開始自己定位问题,并且開始具有“前瞻性”。思考一些问题未来可能存在的潜在情况。也開始逐步关注一些内在原理。只是,可能是艺高人胆大。这些人有可能会犯一些不该犯的错误。他们一般是一些十分优秀的程序设计者。非常多时候可能是为了展现自己的技术能力,会将一些不值得去做的事情不断细化和优化。或者去做一些别人做过的事情,假设由于这样丢掉主业务,则通常说它是过度优化、过度设计、反复制造。
作者本身也有相同的亲身经历,而非常矛盾的在于是否真的是过度设计。在不同的场景下会有不同的看法和评价。因此这个阶段的同学,一般会有一个纠结期。在这个阶段的人開始讲究内外双修,也相同是一个积土成山、积水成渊的过程,由于有一定的功底。学习非常多知识都非常快,在知识面上会有非常大的突破,在知识点上也会逐步加深,可能在工作中不论是业务还是技术上都有了非常多的选择。被觉得是工作能力非常强的人。一些非常“牛”的开发者就会開始意识到非常多代码怎样去编写会更优雅、更加高效,用更简单的代码搞定很多其它的问题。但还未上升到系统级别和架构级别。
可能更高级别的人開始具有非常强的全局观,让系统全局更加具有可维护性和伸缩性,系统性能良好,稳定性十足,能搞定各类架构、部署、规范化等相关的问题,在某些领域上也是说话非常有分量的人物。他们可能会花非常多时间去写通用模型和设计,将难题简单化,解决大家解决不了的难题。一般会尽量让系统的维护变成一条配置或是几条简单代码,可是能够顶得上一群人写一堆代码,这就是特种兵程序猿的“快”、“准”、“狠”、“稳”。
这里的各种级别仅仅是作者“自言自语”,并不代表什么。要做到没有级别在心中才干真正让自己高速成长。
另外,看了这些级别并不代表今天我是刚開始学习的人,明天将不好的习惯改掉后就“脱胎换骨”了,也并不代表自己在某件小事情上有了大师的风范就代表自己是大师了。这些东西都是经历一些事情后才会形成一些自然意识,我们仅仅是有意识地去学习他们为什么会这样做事情,为什么年轻人比老员工有活力。但通常来讲“姜还是老的辣”。
本书读者对象
□ 适合对象
(1)有一定Java基础,并希望能在Java技术上有所成长的人。
本书学习有一定门槛,假设是刚開始学习的人,则能够先以书中的一些样例为引导,希望了解为什么的时候。再来看当中的解释。
(2)对于能静心看书的刚開始学习的人,能够迭代着看本书。
尽管有一定门槛,只是刚開始学习的人仅仅要能静心,迭代着读几次后,你或许也能体会出里面有非常多思想、方法、解决这个问题的手段、看问题的側面,甚至面对问题的心态。那么也能够受益良多。
(3)本书是一个载体,一个推崇自我修为、内外双修的载体,修行看个人。所以适合于想要以自我提升为主要目的的读者。
(4)工作一段时间,对知识和发展的方向非常迷茫,甚至对某些观念也比較迷茫。可是又渴望去解决这些问题,渴望自己成长。渴望自己能找到道路的人。
□ 不适合对象
(1)Java方面的高手和牛人,由于这本书并不能助你从牛人变成大师。
(2)做client(如Android)或嵌入式的Java程序猿,由于书中大多内容是以服务器端Java来解说的。极少考虑client的问题。
(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并发是怎么样的。除了client程序及单片机等。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章,谈谈实际工作中常常会遇到的“坑”,这些坑不easy被发现,可是我们常常easy掉进去,希望大家知道的不仅仅是这些坑,而是通过这些坑了解到,众多技术都是一把“双刃剑,有优点必有坏处”,仅仅有最佳的场景选择最合适的技术,学会怎样去量化与选择,同一时候须要了解到如今的工作对个人素养的要求越来越高。
第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就可以。
迷惑1:equals()不就是对照值的吗?为何说相似?
答曰:一日偶遇怪侠“蜗牛大师”一枚,赐予神剑于数人,猎人将其用于打猎;农夫将它用于劈材。将军用它保家卫国;侠客用它行侠仗义、惩奸除恶。等等。
比如:在对照一些project的图纸尺寸的时候,由于尺寸都会存在细节误差,能够觉得宽度和高度比較接近。就能够返回true。而不一定非要精确匹配。
另外。图纸纸张的属性除了长度、宽度外,还有如名称、存放位置、卷号等属性,可是我们可能仅仅须要对照它的长度与宽度。在这个范围内其余的属性不会考虑。也就是说。两个对象的值是否相同是自己的业务决定的。而不是Java语言来决定的。
感悟:变通,让标准变为价值,给你一种思想和标准。你能够有不同的使用。不能死扣定理,我们要解决这个问题!
迷惑2:equals()重写后,一般会重写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。
easy出错:JVM仅仅会优化它能够帮你优化的部分。它并非对全部的内容都能够优化。比如,就拿上面叠加字符串的样例来说。假设几个字符串叠加中出现了“变量”,即在编译时。还不确定详细的值是多少。那么JVM是不会去做这种编译时合并的。
而JVM详细会做什么样的优化,不做什么样的优化,须要我们不断去学习。才干把工作做得更好。
同理证明的道理:String的“+”操作并不一定比StringBuilder.append()慢,假设是编译时合并就会更快,由于在执行时是直接获取的,根本不须要再去运算。同理。千万不要坚定地觉得什么方式快、什么方式慢,一定要讲究场景。而为什么在非常多样例中StringBuilder. append()比String的“+”操作快呢?在后文中,胖哥会继续介绍原因。
====>篇幅所限,就贴这些吧。
PS:
假设一些小伙伴在试读样章、前言后。感觉本书真的非常适合自己,可是个人经济方面存在压力(比如还在待业找工作、学生之类)。那么能够联系小胖,小胖能够掏钱买这本书送给相应的小伙伴!这方面不要觉得不好意思。为求知没什么大不了的。小胖觉得假设自己的书能帮助到别人内心也会非常开心的。到眼在小胖也送书给很多小伙伴也有类似的需求!
版权声明:本文博客原创文章。博客,未经同意,不得转载。