來源:北大青鳥總部 2019年10月11日 10:02
本文作者: java高級架構(gòu)進階
最近,有小伙伴問我:“java是什么?現(xiàn)在學(xué)習(xí)還晚嗎?”,你學(xué)習(xí)一門技術(shù)的最佳時機是三年前,其次是現(xiàn)在。”這句話對于哪一種行業(yè)都很適用,如果你已經(jīng)學(xué)習(xí)過Java,那么恭喜你你很有先見之明,如果你并不了解Java,這篇文章帶你快速掌握Java的幾個核心知識點。
一、Java特點
1、 面向?qū)ο?/span>
盡管受到其前輩的影響,但Java沒被設(shè)計成兼容其他語言源代碼的程序。這允許Java開發(fā)組自由地從零開始。這樣做的一個結(jié)果是,Java語言可以更直接、更易用、更實際的接近對象。Java的對象模型既簡單又容易擴展,對于簡單數(shù)據(jù)類型,例如整數(shù),它保持了高性能,但不是對象。
2、 解釋性和高性能
字節(jié)碼可以在提供Java虛擬機(JVM)的任何一種系統(tǒng)上被解釋執(zhí)行。早先的許多嘗試解決跨平臺的方案對性能要求都很高。其他解釋執(zhí)行的語言系統(tǒng),如BASIC,Tcl,PERL都有無法克服的性能缺陷。然而,Java卻可以在非常低檔的CPU上順利運行。前面已解釋過,Java確實是一種解釋性語言,Java的字節(jié)碼經(jīng)過仔細設(shè)計,因而很容易便能使用JIT編譯技術(shù)將字節(jié)碼直接轉(zhuǎn)換成高性能的本機代碼。Java運行時系統(tǒng)在提供這個特性的同時仍具有平臺獨立性,因而“高效且跨平臺”對Java來說不再矛盾。
3、 動態(tài)
Java程序帶有多種的運行時類型信息,用于在運行時校驗和解決對象訪問問題。這使得在一種安全、有效的方式下動態(tài)地連接代碼成為可能,對小應(yīng)用程序環(huán)境的健壯性也十分重要,因為在運行時系統(tǒng)中,字節(jié)碼內(nèi)的小段程序可以動態(tài)地被更新。
二、面向?qū)ο蟮木幊?/span>
2.1 抽象
面向?qū)ο缶幊痰囊粋€實質(zhì)性的要素是抽象。人們通過抽象(abstraction)處理復(fù)雜性。
例如,人們不會把一輛汽車想象成由幾萬個互相獨立的部分所組成的一套裝置,而是把汽車想成一個具有自己獨特行為的對象。這種抽象使人們可以很容易地將一輛汽車開到雜貨店,而不會因組成汽車各部分零件過于復(fù)雜而不知所措。傳統(tǒng)的面向過程程序的數(shù)據(jù)經(jīng)過抽象可用若干個組成對象表示,程序中的過程步驟可看成是在這些對象之間進行消息收集。這樣,每一個對象都有它自己的獨特行為特征。你可以把這些對象當(dāng)作具體的實體,讓它們對告訴它們做什么事的消息作出反應(yīng)。這是面向?qū)ο缶幊痰谋举|(zhì)。面向?qū)ο蟮母拍钍?/span>Java 的核心。
2.2面向?qū)ο缶幊痰?個原則
所有面向?qū)ο蟮木幊陶Z言都提供幫助你實現(xiàn)面向?qū)ο竽P偷臋C制,這些機制是封裝,繼承及多態(tài)性。現(xiàn)在讓我們來看一下它們的概念。
封裝
封裝(Encapsulation)是將代碼及其處理的數(shù)據(jù)綁定在一起的一種編程機制,該機制保證了程序和數(shù)據(jù)都不受外部干擾且不被誤用。理解封裝性的一個方法就是把它想成一個黑匣子,它可以阻止在外部定義的代碼隨意訪問內(nèi)部代碼和數(shù)據(jù)。對黑匣子內(nèi)代碼和數(shù)據(jù)的訪問通過一個適當(dāng)定義的接口嚴(yán)格控制。
Java封裝的基本單元是類。盡管類將在以后章節(jié)詳細介紹。現(xiàn)在仍有必要對它作一下簡單的討論。類是一種邏輯結(jié)構(gòu),而對象是真正存在的物理實體。如果你對C/C++熟悉,可以這樣理解:Java程序員所稱的方法,就是C/C++程序員所稱的函數(shù)(function)。在完全用Java編寫的程序中,方法定義如何使用成員變量。這意味著一個類的行為和接口是通過方法來定義的,類這些方法對它的實例數(shù)據(jù)進行操作。
繼承
繼承(Inheritance)是一個對象獲得另一個對象的屬性的過程。繼承很重要,因為它支持了按層分類的概念。使用了繼承,一個對象就只需定義使它在所屬類中獨一無二的屬性即可,因為它可以從它的父類那兒繼承所有的通用屬性。
繼承性與封裝性相互作用。如果一個給定的類封裝了一些屬性,那么它的任何子類將具有同樣的屬性,而且還添加了子類自己特有的屬性。這是面向?qū)ο蟮某绦蛟趶?fù)雜性上呈線性而非幾何性增長的一個關(guān)鍵概念。新的子類繼承它的所有祖先的所有屬性。它不與系統(tǒng)中其余的多數(shù)代碼產(chǎn)生無法預(yù)料的相互作用。
多態(tài)性
多態(tài)性是允許一個接口被多個同類動作使用的特性,具體使用哪個動作與應(yīng)用場合有關(guān),下面我們以一個后進先出型堆棧為例進行說明。假設(shè)你有一個程序,需要3種不同類型的堆棧。一個堆棧用于整數(shù)值,一個用于浮點數(shù)值,一個用于字符。盡管堆棧中存儲的數(shù)據(jù)類型不同,但實現(xiàn)每個棧的算法是一樣的。如果用一種非面向?qū)ο蟮恼Z言,你就要創(chuàng)建3個不同的堆棧程序,每個程序一個名字。但是,如果使用Java,由于它具有多態(tài)性,你就可以創(chuàng)建一個通用的堆棧程序集,它們共享相同的名稱。多態(tài)性的概念經(jīng)常被說成是“一個接口,多種方法”。這意味著可以為一組相關(guān)的動作設(shè)計一個通用的接口。多態(tài)性允許同一個接口被必于同一類的多個動作使用,這樣就降低了程序的復(fù)雜性。選擇應(yīng)用于每一種情形的特定的動作(specific action)(即方法)是編譯器的任務(wù),程序員無需手工進行選擇。你只需記住并且使用通用接口即可。
三、 hashmap hashtable
HashMap 是一個散列表,它存儲的內(nèi)容是鍵值對(key-value)映射。HashMap 繼承于AbstractMap,實現(xiàn)了Map、Cloneable、java.io.Serializable接口。
HashMap 的實現(xiàn)不是同步的,這意味著它不是線程安全的。它的key、value都可以為null。此外,HashMap中的映射不是有序的。HashMap的實例有兩個參數(shù)影響其性能:“初始容量” 和 “加載因子”。容量是哈希表中桶的數(shù)量,初始容量 只是哈希表在創(chuàng)建時的容量。加載因子 是哈希表在其容量自動增加之前可以達到多滿的一種尺度。當(dāng)哈希表中的條目數(shù)超出了加載因子與當(dāng)前容量的乘積時,則要對該哈希表進行 rehash 操作(即重建內(nèi)部數(shù)據(jù)結(jié)構(gòu)),從而哈希表將具有大約兩倍的桶數(shù)。
四. jvm 內(nèi)存模型
程序計數(shù)器
每個線程有要有一個獨立的程序計數(shù)器,記錄下一條要運行的指令。線程私有的內(nèi)存區(qū)域。如果執(zhí)行的是JAVA方法,計數(shù)器記錄正在執(zhí)行的java字節(jié)碼地址,如果執(zhí)行的是native方法,則計數(shù)器為空。
虛擬機棧
線程私有的,與線程在同一時間創(chuàng)建。管理JAVA方法執(zhí)行的內(nèi)存模型。
本地方法區(qū)
和虛擬機棧功能相似,但管理的不是JAVA方法,是本地方法
方法區(qū)
線程共享的,用于存放被虛擬機加載的類的元數(shù)據(jù)信息:如常量、靜態(tài)變量、即時編譯器編譯后的代碼。也稱為永久代。
JAVA 堆
線程共享的,存放所有對象實例和數(shù)組。垃圾回收的主要區(qū)域??梢苑譃樾律屠夏甏?/span>(tenured)。
五、 運行時類型信息(RTTI + 反射)
概念—RTTI:運行時類型信息使得你可以在程序運行時發(fā)現(xiàn)和使用類型信息。
使用方式:Java是如何讓我們在運行時識別對象和類的信息的,主要有兩種方式(還有輔助的第三種方式,見下描述):
一種是“傳統(tǒng)的”RTTI,它假定我們在編譯時已經(jīng)知道了所有的類型,比如Shape s = (Shape)s1;另一種是“反射”機制,它運行我們在運行時發(fā)現(xiàn)和使用類的信息,即使用Class.forName()。其實還有第三種形式,就是關(guān)鍵字instanceof,它返回一個bool值,它保持了類型的概念,它指的是“你是這個類嗎?或者你是這個類的派生類嗎?”。而如果用==或equals比較實際的Class對象,就沒有考慮繼承—它或者是這個確切的類型,或者不是。
工作原理
要理解RTTI在Java中的工作原理,首先必須知道類型信息在運行時是如何表示的,這項工作是由稱為Class對象的特殊對象完成的,它包含了與類有關(guān)的信息。Java送Class對象來執(zhí)行其RTTI,使用類加載器的子系統(tǒng)實現(xiàn)。
無論何時,只要你想在運行時使用類型信息,就必須首先獲得對恰當(dāng)?shù)?/span>Class對象的引用
反射與RTTI的區(qū)別
RTTI與反射之間真正的區(qū)別只在于:對RTTI來說,編譯器在編譯時打開和檢查.class文件(也就是可以用普通方法調(diào)用對象的所有方法);而對于反射機制來說,.class文件在編譯時是不可獲取的,所以是在運行時打開和檢查.class文件。
六. 即時編譯器技術(shù) — JIT
Java虛擬機中有許多附加技術(shù)用以提升速度,尤其是與加載器操作相關(guān)的,被稱為“即時”(Just-In-Time,JIT)編譯器的技術(shù)。這種技術(shù)可以把程序全部或部分翻譯成本地機器碼(這本來是JVM的工作),程序運行速度因此得以提升。當(dāng)需要裝載某個類時,編譯器會先找到其.class文件,然后將該類的字節(jié)碼裝入內(nèi)存。此時,有兩種方案可供選擇:
(1)一種就是讓即時編譯器編譯所有代碼。
(2)另一種做法稱為惰性評估(lazy evaluation),意思是即時編譯器只在必要的時候才編譯代碼,這樣,從不會被執(zhí)行的代碼也許就壓根不會被JIT所編譯。
七、 final關(guān)鍵字
對final關(guān)鍵字的誤解
當(dāng)final修飾的是基本數(shù)據(jù)類型時,它指的是數(shù)值恒定不變(就是編譯期常量,如果是static final修飾,則強調(diào)只有一份),而對對象引用而不是基本類型運用final時,其含義會有一點令人迷惑,因為用于對象引用時,final使引用恒定不變,一旦引用被初始化指向一個對象,就無法再把它指向另一個對象。然而,對象其自身卻是可以被修改的,Java并未提供使任何對象恒定不變的途徑(但可以自己編寫類以取得使對象恒定不變的效果),這一限制同樣適用數(shù)組,它也是對象。
以上是我們在學(xué)習(xí)Java時需要掌握的基本點和一些關(guān)鍵的重難點。了解他們對我們學(xué)習(xí)Java很重要。