最全的JAVA知識(shí)匯總(附講解和思維導(dǎo)圖)

jvm 一行代碼是怎么運(yùn)行的

首先,java代碼會(huì)被編譯成字節(jié)碼,字節(jié)碼就是java虛擬機(jī)定義的一種編碼格式,需要java虛擬機(jī)才能夠解析,java虛擬機(jī)需要將字節(jié)碼轉(zhuǎn)換成機(jī)器碼才能在cpu上執(zhí)行。 我們可以用硬件實(shí)現(xiàn)虛擬機(jī),這樣雖然可以提高效率但是就沒(méi)有了一次編譯到處運(yùn)行的特性了,所以一般在各個(gè)平臺(tái)上用軟件來(lái)實(shí)現(xiàn),目前的虛擬機(jī)還提供了一套運(yùn)行環(huán)境來(lái)進(jìn)行垃圾回收,數(shù)組越界檢查,權(quán)限校驗(yàn)等。虛擬機(jī)一般將一行字節(jié)碼解釋成機(jī)器碼然后執(zhí)行,稱(chēng)為解釋執(zhí)行,也可以將一個(gè)方法內(nèi)的所有字節(jié)碼解釋成機(jī)器碼之后在執(zhí)行,前者執(zhí)行效率低,后者會(huì)導(dǎo)致啟動(dòng)時(shí)間慢,一般根據(jù)二八法則,將百分之20的熱點(diǎn)代碼進(jìn)行即時(shí)編譯。JIT編譯的機(jī)器碼存放在一個(gè)叫codecache的地方,這塊內(nèi)存屬于堆外內(nèi)存,如果這塊內(nèi)存不夠了,那么JIT編譯器將不再進(jìn)行即時(shí)編譯,可能導(dǎo)致程序運(yùn)行變慢。

站在用戶(hù)的角度思考問(wèn)題,與客戶(hù)深入溝通,找到秀峰網(wǎng)站設(shè)計(jì)與秀峰網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶(hù)體驗(yàn)好的作品,建站類(lèi)型包括:成都做網(wǎng)站、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、虛擬空間、企業(yè)郵箱。業(yè)務(wù)覆蓋秀峰地區(qū)。

jvm如何加載一個(gè)類(lèi)

第一步:加載,雙親委派:?jiǎn)?dòng)類(lèi)加載器(jre/lib),系統(tǒng)擴(kuò)展類(lèi)加載器(ext/lib),應(yīng)用類(lèi)加載器(classpath),前者為c++編寫(xiě),所以系統(tǒng)加載器的parent為空,后面兩個(gè)類(lèi)加載器都是通過(guò)啟動(dòng)類(lèi)加載器加載完成后才能使用。加載的過(guò)程就是查找字節(jié)流,可以通過(guò)網(wǎng)絡(luò),也可以自己在代碼生成,也可以來(lái)源一個(gè)jar包。另外,同一個(gè)類(lèi),被不同的類(lèi)加載器加載,那么他們將不是同一個(gè)類(lèi),java中通過(guò)類(lèi)加載器和類(lèi)的名稱(chēng)來(lái)界定唯一,所以我們可以在一個(gè)應(yīng)用成存在多個(gè)同名的類(lèi)的不同實(shí)現(xiàn)。

第二步:鏈接:(驗(yàn)證,準(zhǔn)備,解析) 驗(yàn)證主要是校驗(yàn)字節(jié)碼是否符合約束條件,一般在字節(jié)碼注入的時(shí)候關(guān)注的比較多。準(zhǔn)備:給靜態(tài)字段分配內(nèi)存,但是不會(huì)初始化,解析主要是為了將符號(hào)引用轉(zhuǎn)換為實(shí)際引用,可能會(huì)觸發(fā)方法中引用的類(lèi)的加載。

第三步:初始化,如果賦值的靜態(tài)變量是基礎(chǔ)類(lèi)型或者字符串并且是final的話,該字段將被標(biāo)記為常量池字段,另外靜態(tài)變量的賦值和靜態(tài)代碼塊,將被放在一個(gè)叫cinit的方法內(nèi)被執(zhí)行,為了保證cinit方法只會(huì)被執(zhí)行一次,這個(gè)方法會(huì)加鎖,我們一般實(shí)現(xiàn)單例模式的時(shí)候?yàn)楸WC線程安全,會(huì)利用類(lèi)的初始化上的鎖。 初始化只有在特定條件下才會(huì)被觸發(fā),例如new 一個(gè)對(duì)象,反射被調(diào)用,靜態(tài)方法被調(diào)用等。

java對(duì)象的內(nèi)存布局

java中每一個(gè)非基本類(lèi)型的對(duì)象,都會(huì)有一個(gè)對(duì)象頭,對(duì)象頭中有64位作為標(biāo)記字段,存儲(chǔ)對(duì)象的哈希碼,gc信息,鎖信息,另外64位存儲(chǔ)class對(duì)象的引用指針,如果開(kāi)啟指針壓縮的話,該指針只需要占用32位字節(jié)。

Java對(duì)象中的字段,會(huì)進(jìn)行重排序,主要為了保證內(nèi)存對(duì)齊,使其占用的空間正好是8的倍數(shù),不足8的倍數(shù)會(huì)進(jìn)行填充,所以想知道一個(gè)屬性相對(duì)對(duì)象其始地址的偏移量需要通過(guò)unsafe里的fieldOffset方法,內(nèi)存對(duì)齊也為了避免讓一個(gè)屬性存放在兩個(gè)緩存行中,disruptor中為了保證一個(gè)緩存行只能被一個(gè)屬性占用,也會(huì)用空對(duì)象進(jìn)行填充,因?yàn)槿绻推渌麑?duì)象公用一個(gè)緩存行,其他對(duì)象的失效會(huì)將整個(gè)緩存行失效,影響性能開(kāi)銷(xiāo),jdk8中引入了contended注解來(lái)讓一個(gè)屬性獨(dú)占一個(gè)緩存行,內(nèi)部也是進(jìn)行填充,用空間換取時(shí)間,如何計(jì)算一個(gè)對(duì)象占用多少內(nèi)存,如果不精確的話就進(jìn)行遍歷然后加上對(duì)象頭,這種情況沒(méi)辦法考慮重排序和填充,如果精確的話只能通過(guò)javaagent的instrument工具。

反射的原理

反射真的慢么?

首先class.forname和class.getmethod 第一個(gè)是一個(gè)native方法,第二個(gè)會(huì)遍歷自己和父類(lèi)中的方法,并返回方法的一個(gè)拷貝,所以這兩個(gè)方法性能都不好,建議在應(yīng)用層進(jìn)行緩存。 而反射的具體調(diào)用有兩種方式,一種是調(diào)用本地native方法,一種是通過(guò)動(dòng)態(tài)字節(jié)碼生成一個(gè)類(lèi)來(lái)調(diào)用,默認(rèn)采用第一種,當(dāng)被調(diào)用15次之后,采用第二種動(dòng)態(tài)字節(jié)碼方式,因?yàn)樯勺止?jié)碼也耗時(shí),如果只調(diào)用幾次沒(méi)必要,而第一種方式由于需要在java和c++之間切換,native 方法本身性能消耗嚴(yán)重,所以對(duì)于熱點(diǎn)代碼頻繁調(diào)用反射的話,性能并不會(huì)很差。

屬性的反射,采用unsafe類(lèi)中setvalue來(lái)實(shí)現(xiàn),需要傳入該屬性相對(duì)于對(duì)象其始地址的偏移量,也就是直接操作內(nèi)存。其實(shí)就是根據(jù)這個(gè)屬性在內(nèi)存中的起始地址和類(lèi)型來(lái)讀取一個(gè)字段的值,在LockSupport類(lèi)中,park和unpark方法,設(shè)置誰(shuí)將線程掛起的時(shí)候也有用到這種方式。

動(dòng)態(tài)代理

java本身的動(dòng)態(tài)代理也是通過(guò)字節(jié)碼實(shí)現(xiàn)的

Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)

工具類(lèi)中需要提供 類(lèi)加載器,需要實(shí)現(xiàn)的接口,攔截器的實(shí)現(xiàn),也就是需要在InvocationHandler中調(diào)用原方法并做增強(qiáng)處理。并且這個(gè)實(shí)現(xiàn),一定會(huì)被放到新生成的動(dòng)態(tài)代理類(lèi)里。

生成動(dòng)態(tài)代理類(lèi)的步驟:先通過(guò)聲明的接口生成一個(gè)byte數(shù)組,這個(gè)數(shù)組就是字節(jié)流,通過(guò)傳入的類(lèi)加載進(jìn)行加載生成一個(gè)class對(duì)象,這個(gè)class 里面有個(gè)構(gòu)造方法接收一個(gè)參數(shù),這個(gè)參數(shù)就是InvocationHandler,通過(guò)這個(gè)構(gòu)造方法的反射獲取一個(gè)實(shí)例類(lèi),在這個(gè)class里面,接口的實(shí)現(xiàn)中會(huì)調(diào)用InvocationHandler,而這個(gè)class對(duì)象為了防止生成太多又沒(méi)有被回收,所以是一個(gè)弱引用對(duì)象。

jvm的內(nèi)存模型

并發(fā)問(wèn)題的根源:可見(jiàn)性,原子性,亂序執(zhí)行

java內(nèi)存模型定義了一些規(guī)則來(lái)禁止cpu緩存和編譯器優(yōu)化,happen-before用來(lái)描述兩個(gè)操作的內(nèi)存的可見(jiàn)性,有以下6條

  • 1.程序的順序執(zhí)行,前一個(gè)語(yǔ)句對(duì)后一個(gè)語(yǔ)句可見(jiàn) (當(dāng)兩個(gè)語(yǔ)句沒(méi)有依賴(lài)的情況下還是可以亂序執(zhí)行)

  • 2.volatile變量的寫(xiě)對(duì)另一個(gè)線程的讀可見(jiàn)

  • 3.happen-before 具有傳遞性

  • 4.一個(gè)線程對(duì)鎖的釋放對(duì)另外一個(gè)線程的獲取鎖可見(jiàn) (也就是一個(gè)線程在釋放鎖之前對(duì)共享變量的操作,另外一個(gè)線程獲取鎖后會(huì)看的到)

  • 5.線程a調(diào)用了線程b的start()方法,那么線程a在調(diào)用start方法之前的操作,對(duì)線程b內(nèi)的run()方法可見(jiàn)

  • 6.線程a調(diào)用了線程b的join方法,那么線程b里的所有操作,將對(duì)線程a調(diào)用join之后的操作可見(jiàn)。

jvm的垃圾回收

兩種實(shí)現(xiàn):引用計(jì)數(shù)和可達(dá)性分析,引用計(jì)數(shù)會(huì)出現(xiàn)循環(huán)引用的問(wèn)題,目前一般采用可達(dá)性分析。

為了保證程序運(yùn)行線程和垃圾回收線程不會(huì)發(fā)生并發(fā)影響,jvm采用安全點(diǎn)機(jī)制來(lái)實(shí)現(xiàn)stop the world,也就是當(dāng)垃圾收集線程發(fā)起stop the world請(qǐng)求后,工作線程開(kāi)始進(jìn)行安全點(diǎn)檢測(cè),只有當(dāng)所有線程都進(jìn)入安全點(diǎn)之后,垃圾收集線程才開(kāi)始工作,在垃圾收集線程工作過(guò)程中,工作線程每執(zhí)行一行代碼都會(huì)進(jìn)行安全點(diǎn)檢測(cè),如果這行代碼安全就繼續(xù)執(zhí)行,如果這行代碼不安全就將該線程掛起,這樣可以保證垃圾收集線程運(yùn)行過(guò)程中,工作線程也可以繼續(xù)執(zhí)行。

安全點(diǎn):例如阻塞線程肯定是安全點(diǎn),運(yùn)行的jni線程如果不訪問(wèn)java對(duì)象也是安全的,如果線程正在編譯生成機(jī)器碼那他也是安全的,Java虛擬機(jī)在有垃圾回收線程執(zhí)行期間,每執(zhí)行一個(gè)字節(jié)碼都會(huì)進(jìn)行安全檢測(cè)。

基礎(chǔ)垃圾收集算法:清除算法會(huì)造成垃圾碎片,清除后整理壓縮浪費(fèi)cpu耗時(shí),復(fù)制算法浪費(fèi)內(nèi)存。

基礎(chǔ)假設(shè):大部分的java對(duì)象只存活了一小段時(shí)間,只有少部分java對(duì)象存活很久。新建的對(duì)象放到新生代,當(dāng)經(jīng)過(guò)多次垃圾回收還存在的,就把它移動(dòng)到老年代。針對(duì)不同的區(qū)域采用不同的算法。因?yàn)樾律膶?duì)象存活周期很短,經(jīng)常需要垃圾回收,所以需要采用速度最快的算法,也就是復(fù)制,所以新生代會(huì)分成兩塊。一塊eden區(qū),兩塊大小相同的survivor區(qū)。

新的對(duì)象默認(rèn)在eden區(qū)進(jìn)行分配,由于堆空間是共享的,所以分配內(nèi)存需要加鎖同步,不然會(huì)出現(xiàn)兩個(gè)對(duì)象指向同一塊內(nèi)存,為了避免頻繁的加鎖,一個(gè)線程可以申請(qǐng)一塊連續(xù)內(nèi)存,后續(xù)內(nèi)存的分配就在這里進(jìn)行,這個(gè)方案稱(chēng)為tlab。tlab里面維護(hù)兩個(gè)指針,一個(gè)是當(dāng)前空余內(nèi)存起始位置,另外一個(gè)tail指向尾巴申請(qǐng)的內(nèi)存結(jié)束位置,分配內(nèi)存的時(shí)候只需要進(jìn)行指針加法并判斷是否大于tail,如果超過(guò)則需要重新申請(qǐng)tlab。

如果eden區(qū)滿(mǎn)了則會(huì)進(jìn)行一次minorGc ,將eden區(qū)的存活對(duì)象和from區(qū)的對(duì)象移動(dòng)到to區(qū),然后交換from和to的指針。

垃圾收集器的分類(lèi):針對(duì)的區(qū)域,老年代還是新生代,串行還是并行,采用的算法分類(lèi)復(fù)制還是標(biāo)記整理

g1 基于可控的停頓時(shí)間,增加吞吐量,取代cms g1將內(nèi)存分為多個(gè)塊,每個(gè)塊都可能是 eden survivor old 三種之一 首先清除全是垃圾的快 這樣可以快速釋放內(nèi)存。

如果發(fā)現(xiàn)JVM經(jīng)常進(jìn)行full gc 怎么排查?

不停的進(jìn)行full gc表示可能老年代對(duì)象占有大小超過(guò)閾值,并且經(jīng)過(guò)多次full gc還是沒(méi)有降到閾值以下,所以猜測(cè)可能老年代里有大量的數(shù)據(jù)存活了很久,可能是出現(xiàn)了內(nèi)存泄露,也可能是緩存了大量的數(shù)據(jù)一直沒(méi)有釋放,我們可以用jmap將gc日志dump下來(lái),分析下哪些對(duì)象的實(shí)例個(gè)數(shù)很多,以及哪些對(duì)象占用空間最多,然后結(jié)合代碼進(jìn)行分析。

并發(fā)和鎖

線程的狀態(tài)機(jī)

最全的JAVA知識(shí)匯總(附講解和思維導(dǎo)圖)

線程池參數(shù):核心線程數(shù),最大線程數(shù),線程工廠,線程空閑時(shí)間,任務(wù)隊(duì)列,拒絕策略 先創(chuàng)建核心線程,之后放入任務(wù)隊(duì)列,任務(wù)隊(duì)列滿(mǎn)了創(chuàng)建線程直到最大線程數(shù),在超過(guò)最大線程數(shù)就會(huì)拒絕,線程空閑后超過(guò)核心線程數(shù)的會(huì)釋放,核心線程也可以通過(guò)配置來(lái)釋放,針對(duì)那些一天只跑一個(gè)任務(wù)的情況。newCachedThreadPool線程池會(huì)導(dǎo)致創(chuàng)建大量的線程,因?yàn)橛昧送疥?duì)列。

synchronized

同步塊會(huì)有一個(gè)monitorenter和多個(gè)monitorexist ,重量級(jí)鎖是通過(guò)linux內(nèi)核pthread里的互斥鎖實(shí)現(xiàn)的,包含一個(gè)waitset和一個(gè)阻塞隊(duì)列。 自旋鎖,會(huì)不停嘗試獲取鎖,他會(huì)導(dǎo)致其他阻塞的線程沒(méi)辦法獲取到鎖,所以他是不公平鎖,而輕量級(jí)鎖和偏向鎖,均是在當(dāng)前對(duì)象的對(duì)象頭里做標(biāo)記,用cas方法設(shè)置該標(biāo)記,主要用于多線程在不同時(shí)間點(diǎn)獲取鎖,以及單線程獲取鎖的情況,從而避免重量級(jí)鎖的開(kāi)銷(xiāo),鎖的升級(jí)和降級(jí)也需要在安全點(diǎn)進(jìn)行。

  • reentrantlock相對(duì)synchronized的優(yōu)勢(shì):可以控制公平還是非公平,帶超時(shí),響應(yīng)中斷。

  • CyclicBarrier 多個(gè)線程相互等待,只有所有線程全部完成后才通知一起繼續(xù) (調(diào)用await 直到所有線程都調(diào)用await才一起恢復(fù)繼續(xù)執(zhí)行)

  • countdownlatch 一個(gè)線程等待,其他線程執(zhí)行完后它才能繼續(xù)。(調(diào)用await后被阻塞,直到其他地方調(diào)用countdown()將state減到1 這個(gè)地方的其他可以是其他多個(gè)線程也可以其他單個(gè)任務(wù))

  • semaphore 同一個(gè)時(shí)刻只運(yùn)行n個(gè)線程,限制同時(shí)工作的線程數(shù)目。

  • 阻塞隊(duì)列一般用兩個(gè)鎖,以及對(duì)應(yīng)的條件鎖來(lái)實(shí)現(xiàn),默認(rèn)為INTEGER.MAX為容量,而同步隊(duì)列沒(méi)有容量,優(yōu)先級(jí)隊(duì)列內(nèi)部用紅黑樹(shù)來(lái)實(shí)現(xiàn)。

如果要頻繁讀取和插入建議用concurrenthashmap 如果頻繁修改建議用 concurrentskiplistmap,copyonwrite適合讀多寫(xiě)少,寫(xiě)的時(shí)候進(jìn)行拷貝,并加鎖。讀不加鎖,可能讀取到正在修改的舊值。concurrent系列實(shí)際上都是弱一致性,而其他的都是fail-fast,拋出ConcurrentModificationException,而弱一致性允許修改的時(shí)候還可以遍歷。例如concurrent類(lèi)的size方法可能不是百分百準(zhǔn)確。

AQS 的設(shè)計(jì),用一個(gè)state來(lái)表示狀態(tài),一個(gè)先進(jìn)先出的隊(duì)列,來(lái)維護(hù)正在等待的線程,提供了acquire和release來(lái)獲取和釋放鎖,鎖,條件,信號(hào)量,其他并發(fā)工具都是基于aqs實(shí)現(xiàn)。

字符串

字符串可以通過(guò)intern()方法緩存起來(lái),放到永久代,一般一個(gè)字符串申明的時(shí)候會(huì)檢查常量區(qū)是否存在,如果存在直接返回其地址,字符串是final的,他的hashcode算法采用31進(jìn)制相加,字符串的拼接需要?jiǎng)?chuàng)建一個(gè)新的字符串,一般使用stringbuilder。String s1 = "abc"; String s2 = "abc"; String s1 = new String("abc"); s1和s2可能是相等的,因?yàn)槎贾赶虺A砍亍?/p>

集合

  • vector 線程安全,arraylist 實(shí)現(xiàn) randomaccess 通過(guò)數(shù)組實(shí)現(xiàn)支持隨機(jī)訪問(wèn),linkedlist 雙向鏈表可以支持快速的插入和刪除。

  • treeset 依賴(lài)于 treemap 采用紅黑樹(shù)實(shí)現(xiàn),可以支持順序訪問(wèn),但是插入和刪除復(fù)雜度為 log(n)

  • hashset 依賴(lài)于 hashmap 采用哈希算法實(shí)現(xiàn),可以支持常數(shù)級(jí)別的訪問(wèn),但是不能保證有序

  • linkedhashset 在hashset的節(jié)點(diǎn)上加了一個(gè)雙向鏈表,支持按照訪問(wèn)和插入順序進(jìn)行訪問(wèn)

  • hashtable早版本實(shí)現(xiàn),線程安全 不支持空鍵。

  • hashmap:根據(jù)key的hashcode的低位進(jìn)行位運(yùn)算,因?yàn)楦呶粵_突概率較高,根據(jù)數(shù)組長(zhǎng)度計(jì)算某個(gè)key對(duì)應(yīng)數(shù)組位置,類(lèi)似求余算法,在put的時(shí)候會(huì)進(jìn)行初始化或者擴(kuò)容,當(dāng)元素個(gè)數(shù)超過(guò) 數(shù)組的長(zhǎng)度乘以負(fù)載因子的時(shí)候進(jìn)行擴(kuò)容,當(dāng)鏈表長(zhǎng)度超過(guò)8會(huì)進(jìn)行樹(shù)化,數(shù)組的長(zhǎng)度是2的多少次方,主要方便位運(yùn)算,另一個(gè)好處是擴(kuò)容的時(shí)候遷移數(shù)據(jù)只需要遷移一半。當(dāng)要放 15個(gè)元素的時(shí)候,一般數(shù)組初始化的長(zhǎng)度為 15/0.75= 20 然后對(duì)應(yīng)的2的多少次方,那么數(shù)組初始化長(zhǎng)度為 32.

  • ConcurrentHashMap 內(nèi)部維護(hù)了一個(gè)segment數(shù)組,這個(gè)segment繼承自reentrantlock,他本身是一個(gè)hashmap,segment數(shù)組的長(zhǎng)度也就是并發(fā)度,一般為16. hashentry內(nèi)部的value字段為volatile來(lái)保證可見(jiàn)性.size()方法需要獲取所有的segment的鎖,而jdk8的size()方法用一個(gè)數(shù)組存儲(chǔ)每個(gè)segment對(duì)應(yīng)的長(zhǎng)度。

io

輸入輸出流的數(shù)據(jù)源有 文件流,字節(jié)數(shù)組流,對(duì)象流 ,管道。帶緩存的輸入流,需要執(zhí)行flush,reader和writer是字符流,需要根據(jù)字節(jié)流封裝。

bytebuffer里面有position,capcity,limit 可以通過(guò)flip重置換,一般先寫(xiě)入之后flip后在從頭開(kāi)始讀。

文件拷貝 如果用一個(gè)輸入流和一個(gè)輸出流效率太低,可以用transfer方法,這種模式不用到用戶(hù)空間,直接在內(nèi)核進(jìn)行拷貝。

一個(gè)線程一個(gè)連接針對(duì)阻塞模式來(lái)說(shuō)效率很高,但是吞吐量起不來(lái),因?yàn)闆](méi)辦法開(kāi)那么多線程,而且線程切換也有開(kāi)銷(xiāo),一般用多路復(fù)用,基于事件驅(qū)動(dòng),一個(gè)線程去掃描監(jiān)聽(tīng)的連接中是否有就緒的事件,有的話交給工作線程進(jìn)行讀寫(xiě)。一般用這種方式實(shí)現(xiàn)C10K問(wèn)題。

堆外內(nèi)存(direct) 一般適合io頻繁并且長(zhǎng)期占用的內(nèi)存,一般建議重復(fù)使用,只能通過(guò)Native Memory Tracking(NMT)來(lái)診斷,MappedByteBuffer可以通過(guò)FileChannel.map來(lái)創(chuàng)建,可以在讀文件的時(shí)候少一次內(nèi)核的拷貝,直接將磁盤(pán)的地址映射到用戶(hù)空間,使用戶(hù)感覺(jué)像操作本地內(nèi)存一樣,只有當(dāng)發(fā)生缺頁(yè)異常的時(shí)候才會(huì)觸發(fā)去磁盤(pán)加載,一次只會(huì)加載要讀取的數(shù)據(jù)頁(yè),例如rocketmq里一次映射1g的文件,并通過(guò)在每個(gè)數(shù)據(jù)頁(yè)寫(xiě)1b的數(shù)據(jù)進(jìn)行預(yù)熱,將整個(gè)1G的文件都加載到內(nèi)存。

設(shè)計(jì)模式

  • 創(chuàng)建對(duì)象:工廠 構(gòu)建 單例

  • 結(jié)構(gòu)型: 門(mén)面 裝飾 適配器 代理

  • 行為型:責(zé)任鏈 觀察者 模版

  • 封裝(隱藏內(nèi)部實(shí)現(xiàn)) 繼承(代碼復(fù)用) 多態(tài)(方法的重寫(xiě)和重載)

  • 設(shè)計(jì)原則:?jiǎn)我恢肛?zé),開(kāi)關(guān)原則,里氏替換,接口分離,依賴(lài)反轉(zhuǎn)

最全的JAVA知識(shí)匯總(附講解和思維導(dǎo)圖)

網(wǎng)站標(biāo)題:最全的JAVA知識(shí)匯總(附講解和思維導(dǎo)圖)
網(wǎng)頁(yè)路徑:http://muchs.cn/article30/ihdhpo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開(kāi)發(fā)、商城網(wǎng)站網(wǎng)站導(dǎo)航、網(wǎng)站內(nèi)鏈網(wǎng)站收錄、Google

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營(yíng)