java基礎(chǔ)面試

1.java基本數(shù)據(jù)類型

byte:8位烟号,最大存儲(chǔ)數(shù)據(jù)量是255立美,存放的數(shù)據(jù)范圍是-128~127之間癣籽。

short:16位,最大數(shù)據(jù)存儲(chǔ)量是65536程拭,數(shù)據(jù)范圍是-32768~32767之間定踱。

int:32位,最大數(shù)據(jù)存儲(chǔ)容量是2的32次方減1恃鞋,數(shù)據(jù)范圍是負(fù)的2的31次方到正的2的31次方減1崖媚。

long:64位,最大數(shù)據(jù)存儲(chǔ)容量是2的64次方減1山宾,數(shù)據(jù)范圍為負(fù)的2的63次方到正的2的63次方減1。

float:32位鳍徽,數(shù)據(jù)范圍在3.4e-45~1.4e38资锰,直接賦值時(shí)必須在數(shù)字后加上f或F。

double:64位阶祭,數(shù)據(jù)范圍在4.9e-324~1.8e308绷杜,賦值時(shí)可以加d或D也可以不加直秆。

boolean:只有true和false兩個(gè)取值。

char:16位鞭盟,存儲(chǔ)Unicode碼圾结,用單引號(hào)賦值。

String: 為飲用類型

2.java中StringBuilder和StringBuffer的區(qū)別

StringBuffer是線程安全齿诉,可以不需要額外的同步用于多線程中;

StringBuilder是非同步,運(yùn)行于多線程中就需要使用著單獨(dú)同步處理筝野,但是速度就比StringBuffer快多了;

StringBuffer與StringBuilder兩者共同之處:可以通過(guò)append、indert進(jìn)行字符串的操作粤剧。

3.java中集合

List , Set, Map都是接口歇竟,前兩個(gè)繼承至Collection接口,Map為獨(dú)立接口

Set下有HashSet抵恋,LinkedHashSet焕议,TreeSet

List下有ArrayList,Vector弧关,LinkedList

Map下有Hashtable盅安,LinkedHashMap,HashMap世囊,TreeMap

Collection接口下還有個(gè)Queue接口别瞭,有PriorityQueue類

Connection接口:

— List 有序,可重復(fù)

ArrayList

優(yōu)點(diǎn): 底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,查詢快茸习,增刪慢畜隶。

缺點(diǎn): 線程不安全,效率高

Vector

優(yōu)點(diǎn): 底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組号胚,查詢快籽慢,增刪慢。

缺點(diǎn): 線程安全猫胁,效率低

LinkedList

優(yōu)點(diǎn): 底層數(shù)據(jù)結(jié)構(gòu)是鏈表箱亿,查詢慢,增刪快弃秆。

缺點(diǎn): 線程不安全届惋,效率高

—Set 無(wú)序,唯一

HashSet

底層數(shù)據(jù)結(jié)構(gòu)是哈希表。(無(wú)序,唯一)

如何來(lái)保證元素唯一性?

1.依賴兩個(gè)方法:hashCode()和equals()

LinkedHashSet

底層數(shù)據(jù)結(jié)構(gòu)是鏈表和哈希表菠赚。(FIFO插入有序,唯一)

1.由鏈表保證元素有序

2.由哈希表保證元素唯一

TreeSet

底層數(shù)據(jù)結(jié)構(gòu)是紅黑樹脑豹。(唯一,有序)

1. 如何保證元素排序的呢?

自然排序

比較器排序

2.如何保證元素唯一性的呢?

根據(jù)比較的返回值是否是0來(lái)決定


集合

3.1HasMap

Java為數(shù)據(jù)結(jié)構(gòu)中的映射定義了一個(gè)接口java.util.Map衡查,此接口主要有四個(gè)常用的實(shí)現(xiàn)類瘩欺,分別是HashMap、Hashtable、LinkedHashMap和TreeMap

(1) HashMap:它根據(jù)鍵的hashCode值存儲(chǔ)數(shù)據(jù)俱饿,大多數(shù)情況下可以直接定位到它的值歌粥,因而具有很快的訪問(wèn)速度,但遍歷順序卻是不確定的拍埠。 HashMap最多只允許一條記錄的鍵為null失驶,允許多條記錄的值為null。HashMap非線程安全枣购,即任一時(shí)刻可以有多個(gè)線程同時(shí)寫HashMap嬉探,可能會(huì)導(dǎo)致數(shù)據(jù)的不一致。如果需要滿足線程安全坷虑,可以用 Collections的synchronizedMap方法使HashMap具有線程安全的能力甲馋,或者使用ConcurrentHashMap。

(2) Hashtable:Hashtable是遺留類迄损,很多映射的常用功能與HashMap類似定躏,不同的是它承自Dictionary類,并且是線程安全的芹敌,任一時(shí)間只有一個(gè)線程能寫Hashtable痊远,并發(fā)性不如ConcurrentHashMap,因?yàn)镃oncurrentHashMap引入了分段鎖氏捞。Hashtable不建議在新代碼中使用碧聪,不需要線程安全的場(chǎng)合可以用HashMap替換,需要線程安全的場(chǎng)合可以用ConcurrentHashMap替換液茎。

(3) LinkedHashMap:LinkedHashMap是HashMap的一個(gè)子類逞姿,保存了記錄的插入順序,在用Iterator遍歷LinkedHashMap時(shí)捆等,先得到的記錄肯定是先插入的滞造,也可以在構(gòu)造時(shí)帶參數(shù),按照訪問(wèn)次序排序栋烤。

(4) TreeMap:TreeMap實(shí)現(xiàn)SortedMap接口谒养,能夠把它保存的記錄根據(jù)鍵排序,默認(rèn)是按鍵值的升序排序明郭,也可以指定排序的比較器买窟,當(dāng)用Iterator遍歷TreeMap時(shí),得到的記錄是排過(guò)序的薯定。如果使用排序的映射始绍,建議使用TreeMap。在使用TreeMap時(shí)话侄,key必須實(shí)現(xiàn)Comparable接口或者在構(gòu)造TreeMap傳入自定義的Comparator亏推,否則會(huì)在運(yùn)行時(shí)拋出java.lang.ClassCastException類型的異常。

內(nèi)部實(shí)現(xiàn)(存儲(chǔ)結(jié)構(gòu)-字段)

從結(jié)構(gòu)實(shí)現(xiàn)來(lái)講,HashMap是數(shù)組+鏈表+紅黑樹(JDK1.8增加了紅黑樹部分)實(shí)現(xiàn)的径簿,如下如所示。

(1)HashMap類中有一個(gè)非常重要的字段嘀韧,就是 Node[] table篇亭,即哈希桶數(shù)組,明顯它是一個(gè)Node的數(shù)組锄贷。

(2)HashMap就是使用哈希表來(lái)存儲(chǔ)的译蒂。哈希表為解決沖突,可以采用開放地址法和鏈地址法等來(lái)解決問(wèn)題谊却,Java中HashMap采用了鏈地址法柔昼。鏈地址法,簡(jiǎn)單來(lái)說(shuō)炎辨,就是數(shù)組加鏈表的結(jié)合捕透。在每個(gè)數(shù)組元素上都一個(gè)鏈表結(jié)構(gòu),當(dāng)數(shù)據(jù)被Hash后碴萧,得到數(shù)組下標(biāo)乙嘀,把數(shù)據(jù)放在對(duì)應(yīng)下標(biāo)元素的鏈表上。

4.java線程

1.?新建(NEW):新創(chuàng)建了一個(gè)線程對(duì)象破喻。

2.?可運(yùn)行(RUNNABLE):線程對(duì)象創(chuàng)建后虎谢,其他線程(比如main線程)調(diào)用了該對(duì)象的start()方法。該狀態(tài)的線程位于可運(yùn)行線程池中曹质,等待被線程調(diào)度選中婴噩,獲取cpu 的使用權(quán) 。

3.?運(yùn)行(RUNNING):可運(yùn)行狀態(tài)(runnable)的線程獲得了cpu 時(shí)間片(timeslice) 羽德,執(zhí)行程序代碼几莽。

4.?阻塞(BLOCKED):阻塞狀態(tài)是指線程因?yàn)槟撤N原因放棄了cpu 使用權(quán),也即讓出了cpu timeslice玩般,暫時(shí)停止運(yùn)行银觅。直到線程進(jìn)入可運(yùn)行(runnable)狀態(tài),才有機(jī)會(huì)再次獲得cpu timeslice 轉(zhuǎn)到運(yùn)行(running)狀態(tài)坏为。阻塞的情況分三種:

(一). 等待阻塞:運(yùn)行(running)的線程執(zhí)行o.wait()方法究驴,JVM會(huì)把該線程放入等待隊(duì)列(waitting queue)中。

(二). 同步阻塞:運(yùn)行(running)的線程在獲取對(duì)象的同步鎖時(shí)匀伏,若該同步鎖被別的線程占用洒忧,則JVM會(huì)把該線程放入鎖池(lock pool)中。

(三). 其他阻塞:運(yùn)行(running)的線程執(zhí)行Thread.sleep(long ms)或t.join()方法够颠,或者發(fā)出了I/O請(qǐng)求時(shí)熙侍,JVM會(huì)把該線程置為阻塞狀態(tài)。當(dāng)sleep()狀態(tài)超時(shí)、join()等待線程終止或者超時(shí)蛉抓、或者I/O處理完畢時(shí)庆尘,線程重新轉(zhuǎn)入可運(yùn)行(runnable)狀態(tài)。

5.?死亡(DEAD):線程run()巷送、main() 方法執(zhí)行結(jié)束驶忌,或者因異常退出了run()方法,則該線程結(jié)束生命周期笑跛。死亡的線程不可再次復(fù)生付魔。

volatile與synchronized的區(qū)別

1、鎖提供了兩種主要特性:互斥(mutual exclusion)可見性(visibility)飞蹂。

  互斥即一次只允許一個(gè)線程持有某個(gè)特定的鎖,因此可使用該特性實(shí)現(xiàn)對(duì)共享數(shù)據(jù)的協(xié)調(diào)訪問(wèn)協(xié)議陈哑,這樣妻坝,一次就只有一個(gè)線程能夠使用該共享數(shù)據(jù)。

  可見性要更加復(fù)雜一些惊窖,它必須確保釋放鎖之前對(duì)共享數(shù)據(jù)做出的更改對(duì)于隨后獲得該鎖的另一個(gè)線程是可見的 —— 如果沒有同步機(jī)制提供的這種可見性保證惠勒,線程看到的共享 ? ? ? ? 變量可能是修改前的值或不一致的值,這將引發(fā)許多嚴(yán)重問(wèn)題爬坑。(競(jìng)態(tài)條件)

2纠屋、在Java中,為了保證多線程讀寫數(shù)據(jù)時(shí)保證數(shù)據(jù)的一致性,可以采用兩種方式:

 ?同步:如用synchronized關(guān)鍵字,或者使用鎖對(duì)象

 ?使用volatile關(guān)鍵字:用一句話概括volatile,它能夠使變量在值發(fā)生改變時(shí)能盡快地讓其他線程知道。

? ? ?volatile僅能實(shí)現(xiàn)變量修改的可見性盾计,而synchronized則可以保證變量修改的可見性和原子性售担。

? ????volatile不會(huì)造成線程阻塞,synchronized會(huì)造成線程阻塞署辉。

3族铆、 什么是原子操作?

原子操作:一個(gè)或多個(gè)操作在CPU執(zhí)行過(guò)程中不被中斷的特性

當(dāng)我們說(shuō)原子操作時(shí)哭尝,需要分清楚針對(duì)的是CPU指令級(jí)別還是高級(jí)語(yǔ)言級(jí)別哥攘。

“原子操作”的實(shí)質(zhì)其實(shí)并不是指“不可分割”,這只是外在表現(xiàn)材鹦,本質(zhì)在于多個(gè)資源之間有一致性的要求逝淹,操作的中間態(tài)對(duì)外不可見

5.Java鎖的種類

樂(lè)觀鎖:顧名思義桶唐,就是很樂(lè)觀栅葡,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖尤泽,但是在更新的時(shí)候會(huì)判斷一下在此期間別人有沒有去更新這個(gè)數(shù)據(jù)欣簇,可以使用版本號(hào)等機(jī)制规脸。樂(lè)觀鎖適用于多讀的應(yīng)用類型,這樣可以提高吞吐量熊咽,在Java中java.util.concurrent.atomic包下面的原子變量類就是使用了樂(lè)觀鎖的一種實(shí)現(xiàn)方式CAS(Compare and Swap 比較并交換)實(shí)現(xiàn)的莫鸭。

悲觀鎖:總是假設(shè)最壞的情況,每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改横殴,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖黔龟,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)阻塞直到它拿到鎖。比如Java里面的同步原語(yǔ)synchronized關(guān)鍵字的實(shí)現(xiàn)就是悲觀鎖滥玷。

獨(dú)享鎖:是指該鎖一次只能被一個(gè)線程所持有。

共享鎖:是指該鎖可被多個(gè)線程所持有巍棱。

對(duì)于Java ReentrantLock而言惑畴,其是獨(dú)享鎖。但是對(duì)于Lock的另一個(gè)實(shí)現(xiàn)類ReadWriteLock航徙,其讀鎖是共享鎖如贷,其寫鎖是獨(dú)享鎖。

讀鎖的共享鎖可保證并發(fā)讀是非常高效的到踏,讀寫杠袱,寫讀,寫寫的過(guò)程是互斥的窝稿。

獨(dú)享鎖與共享鎖也是通過(guò)AQS來(lái)實(shí)現(xiàn)的楣富,通過(guò)實(shí)現(xiàn)不同的方法,來(lái)實(shí)現(xiàn)獨(dú)享或者共享伴榔。對(duì)于Synchronized而言纹蝴,當(dāng)然是獨(dú)享鎖。

互斥鎖/讀寫鎖

互斥鎖在Java中的具體實(shí)現(xiàn)就是ReentrantLock踪少。

讀寫鎖在Java中的具體實(shí)現(xiàn)就是ReadWriteLock塘安。

可重入鎖

可重入鎖又名遞歸鎖,是指在同一個(gè)線程在外層方法獲取鎖的時(shí)候援奢,在進(jìn)入內(nèi)層方法會(huì)自動(dòng)獲取鎖兼犯。

對(duì)于Java ReetrantLock而言,從名字就可以看出是一個(gè)重入鎖集漾,其名字是Re entrant Lock 重新進(jìn)入鎖切黔。

對(duì)于Synchronized而言,也是一個(gè)可重入鎖具篇∪颇铮可重入鎖的一個(gè)好處是可一定程度避免死鎖。

公平鎖/非公平鎖

公平鎖是指多個(gè)線程按照申請(qǐng)鎖的順序來(lái)獲取鎖栽连。

非公平鎖是指多個(gè)線程獲取鎖的順序并不是按照申請(qǐng)鎖的順序险领,有可能后申請(qǐng)的線程比先申請(qǐng)的線程優(yōu)先獲取鎖侨舆。有可能,會(huì)造成優(yōu)先級(jí)反轉(zhuǎn)或者饑餓現(xiàn)象绢陌。

對(duì)于Java ReetrantLock而言挨下,通過(guò)構(gòu)造函數(shù)指定該鎖是否是公平鎖,默認(rèn)是非公平鎖脐湾。非公平鎖的優(yōu)點(diǎn)在于吞吐量比公平鎖大臭笆。

對(duì)于Synchronized而言,也是一種非公平鎖秤掌。由于其并不像ReentrantLock是通過(guò)AQS的來(lái)實(shí)現(xiàn)線程調(diào)度愁铺,所以并沒有任何辦法使其變成公平鎖。

分段鎖

分段鎖其實(shí)是一種鎖的設(shè)計(jì)闻鉴,并不是具體的一種鎖茵乱,對(duì)于ConcurrentHashMap而言,其并發(fā)的實(shí)現(xiàn)就是通過(guò)分段鎖的形式來(lái)實(shí)現(xiàn)高效的并發(fā)操作孟岛。

我們以ConcurrentHashMap來(lái)說(shuō)一下分段鎖的含義以及設(shè)計(jì)思想瓶竭,ConcurrentHashMap中的分段鎖稱為Segment,它即類似于HashMap(JDK7和JDK8中HashMap的實(shí)現(xiàn))的結(jié)構(gòu)渠羞,即內(nèi)部擁有一個(gè)Entry數(shù)組斤贰,數(shù)組中的每個(gè)元素又是一個(gè)鏈表;同時(shí)又是一個(gè)ReentrantLock(Segment繼承了ReentrantLock)次询。

當(dāng)需要put元素的時(shí)候荧恍,并不是對(duì)整個(gè)hashmap進(jìn)行加鎖,而是先通過(guò)hashcode來(lái)知道他要放在哪一個(gè)分段中屯吊,然后對(duì)這個(gè)分段進(jìn)行加鎖块饺,所以當(dāng)多線程put的時(shí)候,只要不是放在一個(gè)分段中雌芽,就實(shí)現(xiàn)了真正的并行的插入授艰。

但是,在統(tǒng)計(jì)size的時(shí)候世落,可就是獲取hashmap全局信息的時(shí)候淮腾,就需要獲取所有的分段鎖才能統(tǒng)計(jì)。

分段鎖的設(shè)計(jì)目的是細(xì)化鎖的粒度屉佳,當(dāng)操作不需要更新整個(gè)數(shù)組的時(shí)候谷朝,就僅僅針對(duì)數(shù)組中的一項(xiàng)進(jìn)行加鎖操作。

偏向鎖/輕量級(jí)鎖/重量級(jí)鎖

 這三種鎖是指鎖的狀態(tài)武花,并且是針對(duì)Synchronized圆凰。在Java 5通過(guò)引入鎖升級(jí)的機(jī)制來(lái)實(shí)現(xiàn)高效Synchronized。這三種鎖的狀態(tài)是通過(guò)對(duì)象監(jiān)視器在對(duì)象頭中的字段來(lái)表明的体箕。

 偏向鎖是指一段同步代碼一直被一個(gè)線程所訪問(wèn)专钉,那么該線程會(huì)自動(dòng)獲取鎖挑童。降低獲取鎖的代價(jià)。

 輕量級(jí)鎖是指當(dāng)鎖是偏向鎖的時(shí)候跃须,被另一個(gè)線程所訪問(wèn)站叼,偏向鎖就會(huì)升級(jí)為輕量級(jí)鎖,其他線程會(huì)通過(guò)自旋的形式嘗試獲取鎖菇民,不會(huì)阻塞尽楔,提高性能。

 重量級(jí)鎖是指當(dāng)鎖為輕量級(jí)鎖的時(shí)候第练,另一個(gè)線程雖然是自旋阔馋,但自旋不會(huì)一直持續(xù)下去,當(dāng)自旋一定次數(shù)的時(shí)候娇掏,還沒有獲取到鎖呕寝,就會(huì)進(jìn)入阻塞,該鎖膨脹為重量級(jí)鎖驹碍。重量級(jí)鎖會(huì)讓他申請(qǐng)的線程進(jìn)入阻塞,性能降低凡恍。

自旋鎖

在Java中志秃,自旋鎖是指嘗試獲取鎖的線程不會(huì)立即阻塞,而是采用循環(huán)的方式去嘗試獲取鎖嚼酝,這樣的好處是減少線程上下文切換的消耗浮还,缺點(diǎn)是循環(huán)會(huì)消耗CPU。

6.java設(shè)計(jì)模式

什么是設(shè)計(jì)模式? 闽巩?

設(shè)計(jì)模式(Design pattern)是一套被反復(fù)使用钧舌、多數(shù)人知曉的、經(jīng)過(guò)分類編目的涎跨、代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié)洼冻。使用設(shè)計(jì)模式是為了可重用代碼、讓代碼更容易被他人理解隅很、保證代碼可靠性撞牢。 毫無(wú)疑問(wèn),設(shè)計(jì)模式于己于他人于系統(tǒng)都是多贏的叔营,設(shè)計(jì)模式使代碼編制真正工程化,設(shè)計(jì)模式是軟件工程的基石,如同大廈的一塊塊磚石一樣望门。項(xiàng)目中合理的運(yùn)用設(shè)計(jì)模式可以完美的解決很多問(wèn)題甫菠,每種模式在現(xiàn)在中都有相應(yīng)的原理來(lái)與之對(duì)應(yīng),每一個(gè)模式描述了一個(gè)在我們周圍不斷重復(fù)發(fā)生的問(wèn)題婴谱,以及該問(wèn)題的核心解決方案蟹但,這也是它能被廣泛應(yīng)用的原因躯泰。簡(jiǎn)單說(shuō):

模式:在某些場(chǎng)景下,針對(duì)某類問(wèn)題的某種通用的解決方案矮湘。

場(chǎng)景:項(xiàng)目所在的環(huán)境

問(wèn)題:約束條件斟冕,項(xiàng)目目標(biāo)等

解決方案:通用、可復(fù)用的設(shè)計(jì)缅阳,解決約束達(dá)到目標(biāo)磕蛇。

設(shè)計(jì)模式的三個(gè)分類?

創(chuàng)建型模式:對(duì)象實(shí)例化的模式,創(chuàng)建型模式用于解耦對(duì)象的實(shí)例化過(guò)程十办。

結(jié)構(gòu)型模式:把類或?qū)ο蠼Y(jié)合在一起形成一個(gè)更大的結(jié)構(gòu)秀撇。

行為型模式:類和對(duì)象如何交互,及劃分責(zé)任和算法向族。

各分類中模式的關(guān)鍵點(diǎn)

創(chuàng)建型模式

單例模式:某個(gè)類只能有一個(gè)實(shí)例呵燕,提供一個(gè)全局的訪問(wèn)點(diǎn)。

簡(jiǎn)單工廠:一個(gè)工廠類根據(jù)傳入的參量決定創(chuàng)建出那一種產(chǎn)品類的實(shí)例件相。

工廠方法:定義一個(gè)創(chuàng)建對(duì)象的接口再扭,讓子類決定實(shí)例化那個(gè)類。

抽象工廠:創(chuàng)建相關(guān)或依賴對(duì)象的家族夜矗,而無(wú)需明確指定具體類泛范。

建造者模式:封裝一個(gè)復(fù)雜對(duì)象的構(gòu)建過(guò)程,并可以按步驟構(gòu)造紊撕。

原型模式:通過(guò)復(fù)制現(xiàn)有的實(shí)例來(lái)創(chuàng)建新的實(shí)例罢荡。

結(jié)構(gòu)i型模式

適配器模式:將一個(gè)類的方法接口轉(zhuǎn)換成客戶希望的另外一個(gè)接口。

組合模式:將對(duì)象組合成樹形結(jié)構(gòu)以表示“”部分-整體“”的層次結(jié)構(gòu)对扶。

裝飾模式:動(dòng)態(tài)的給對(duì)象添加新的功能区赵。

代理模式:為其他對(duì)象提供一個(gè)代理以便控制這個(gè)對(duì)象的訪問(wèn)。

亨元(蠅量)模式:通過(guò)共享技術(shù)來(lái)有效的支持大量細(xì)粒度的對(duì)象浪南。

外觀模式:對(duì)外提供一個(gè)統(tǒng)一的方法笼才,來(lái)訪問(wèn)子系統(tǒng)中的一群接口。

橋接模式:將抽象部分和它的實(shí)現(xiàn)部分分離络凿,使它們都可以獨(dú)立的變化患整。

行為型模式

模板模式:定義一個(gè)算法結(jié)構(gòu),而將一些步驟延遲到子類實(shí)現(xiàn)喷众。

解釋器模式:給定一個(gè)語(yǔ)言各谚,定義它的文法的一種表示,并定義一個(gè)解釋器到千。

策略模式:定義一系列算法昌渤,把他們封裝起來(lái),并且使它們可以相互替換憔四。

狀態(tài)模式:允許一個(gè)對(duì)象在其對(duì)象內(nèi)部狀態(tài)改變時(shí)改變它的行為膀息。

觀察者模式:對(duì)象間的一對(duì)多的依賴關(guān)系般眉。

備忘錄模式:在不破壞封裝的前提下,保持對(duì)象的內(nèi)部狀態(tài)潜支。

中介者模式:用一個(gè)中介對(duì)象來(lái)封裝一系列的對(duì)象交互甸赃。

命令模式:將命令請(qǐng)求封裝為一個(gè)對(duì)象,使得可以用不同的請(qǐng)求來(lái)進(jìn)行參數(shù)化冗酿。

訪問(wèn)者模式:在不改變數(shù)據(jù)結(jié)構(gòu)的前提下埠对,增加作用于一組對(duì)象元素的新功能。

責(zé)任鏈模式:將請(qǐng)求的發(fā)送者和接收者解耦裁替,使的多個(gè)對(duì)象都有處理這個(gè)請(qǐng)求的機(jī)會(huì)项玛。

迭代器模式:一種遍歷訪問(wèn)聚合對(duì)象中各個(gè)元素的方法,不暴露該對(duì)象的內(nèi)部結(jié)構(gòu)弱判。

7.Object類

Object類是所有類的父類(Object提供了11 個(gè)方法)

1. clone()

保護(hù)方法襟沮,實(shí)現(xiàn)對(duì)象的淺復(fù)制,只有實(shí)現(xiàn)了Cloneable接口才可以調(diào)用該方法昌腰,否則拋出CloneNotSupportedException異常开伏。

2. getClass()

final方法,返回Class類型的對(duì)象遭商,反射來(lái)獲取對(duì)象固灵。

3. toString()

該方法用得比較多,一般子類都有覆蓋株婴,來(lái)獲取對(duì)象的信息怎虫。

4. finalize()

該方法用于釋放資源暑认。因?yàn)闊o(wú)法確定該方法什么時(shí)候被調(diào)用困介,很少使用。

5. equals()

比較對(duì)象的內(nèi)容是否相等

6. hashCode()

該方法用于哈希查找蘸际,重寫了equals方法一般都要重寫hashCode方法座哩。這個(gè)方法在一些具有哈希功能的Collection中用到。

7. wait()

wait方法就是使當(dāng)前線程等待該對(duì)象的鎖粮彤,當(dāng)前線程必須是該對(duì)象的擁有者根穷,也就是具有該對(duì)象的鎖。wait()方法一直等待导坟,直到獲得鎖或者被中斷屿良。wait(long timeout)設(shè)定一個(gè)超時(shí)間隔,如果在規(guī)定時(shí)間內(nèi)沒有獲得鎖就返回惫周。

調(diào)用該方法后當(dāng)前線程進(jìn)入睡眠狀態(tài)尘惧,直到以下事件發(fā)生。

其他線程調(diào)用了該對(duì)象的notify方法递递。

其他線程調(diào)用了該對(duì)象的notifyAll方法喷橙。

其他線程調(diào)用了interrupt中斷該線程啥么。

時(shí)間間隔到了。

此時(shí)該線程就可以被調(diào)度了贰逾,如果是被中斷的話就拋出一個(gè)InterruptedException異常悬荣。

8. notify()

該方法喚醒在該對(duì)象上等待的某個(gè)線程。

9. notifyAll()

該方法喚醒在該對(duì)象上等待的所有線程疙剑。

8.java內(nèi)存

具體的概念:JVM的內(nèi)存可分為3個(gè)區(qū):堆(heap)氯迂、棧(stack)和方法區(qū)(method,也叫靜態(tài)區(qū)):

堆區(qū):?

1.存儲(chǔ)的全部是對(duì)象核芽,每個(gè)對(duì)象都包含一個(gè)與之對(duì)應(yīng)的class的信息(class的目的是得到操作指令) 囚戚;

2.jvm只有一個(gè)堆區(qū)(heap),且被所有線程共享轧简,堆中不存放基本類型和對(duì)象引用驰坊,只存放對(duì)象本身和數(shù)組本身;

棧區(qū):?

1.每個(gè)線程包含一個(gè)棧區(qū)哮独,棧中只保存基礎(chǔ)數(shù)據(jù)類型本身和自定義對(duì)象的引用拳芙;

2.每個(gè)棧中的數(shù)據(jù)(原始類型和對(duì)象引用)都是私有的,其他棧不能訪問(wèn)皮璧;

3.棧分為3個(gè)部分:基本類型變量區(qū)舟扎、執(zhí)行環(huán)境上下文、操作指令區(qū)(存放操作指令)悴务;

方法區(qū)(靜態(tài)區(qū)):?

1.被所有的線程共享睹限,方法區(qū)包含所有的class(class是指類的原始代碼,要?jiǎng)?chuàng)建一個(gè)類的對(duì)象讯檐,首先要把該類的代碼加載到方法區(qū)中羡疗,并且初始化)和static變量。?

2.方法區(qū)中包含的都是在整個(gè)程序中永遠(yuǎn)唯一的元素别洪,如class叨恨,static變量。?


9.java中類加載

jvm的類加載機(jī)制:jvm把描述類的數(shù)據(jù)從class文件中加載到內(nèi)存挖垛,并對(duì)數(shù)據(jù)進(jìn)行校驗(yàn)痒钝,轉(zhuǎn)換解析和初始化,最終形成被jvm使用的Java類型痢毒。


java類加載生命周期

加載

通過(guò)全限定類名來(lái)獲取定義此類的二進(jìn)制字節(jié)流送矩。

將這個(gè)字節(jié)流所代表的靜態(tài)存儲(chǔ)結(jié)構(gòu)轉(zhuǎn)化為方法區(qū)的運(yùn)行時(shí)數(shù)據(jù)結(jié)構(gòu)。

在內(nèi)存中生成一個(gè)代表這個(gè)類的 java.lang.Class 對(duì)象哪替,作為方法區(qū)這個(gè)類的各種數(shù)據(jù)的訪問(wèn)入口栋荸。

驗(yàn)證

驗(yàn)證是連接階段的第一步,這一階段的目的是為了確保 Class 文件的字節(jié)流中包含的信息符合當(dāng)前虛擬機(jī)的要求,并且不會(huì)危害虛擬機(jī)自身的安全蒸其。

文件格式驗(yàn)證:如是否以魔數(shù) 0xCAFEBABE 開頭敏释、主、次版本號(hào)是否在當(dāng)前虛擬機(jī)處理范圍之內(nèi)摸袁、常量合理性驗(yàn)證等钥顽。

此階段保證輸入的字節(jié)流能正確地解析并存儲(chǔ)于方法區(qū)之內(nèi),格式上符合描述一個(gè) Java類型信息的要求靠汁。

元數(shù)據(jù)驗(yàn)證:是否存在父類蜂大,父類的繼承鏈?zhǔn)欠裾_,抽象類是否實(shí)現(xiàn)了其父類或接口之中要求實(shí)現(xiàn)的所有方法蝶怔,字段奶浦、方法是否與父類產(chǎn)生矛盾等。

第二階段踢星,保證不存在不符合 Java 語(yǔ)言規(guī)范的元數(shù)據(jù)信息澳叉。

字節(jié)碼驗(yàn)證:通過(guò)數(shù)據(jù)流和控制流分析,確定程序語(yǔ)義是合法的沐悦、符合邏輯的成洗。例如保證跳轉(zhuǎn)指令不會(huì)跳轉(zhuǎn)到方法體以外的字節(jié)碼指令上。

符號(hào)引用驗(yàn)證:在解析階段中發(fā)生藏否,保證可以將符號(hào)引用轉(zhuǎn)化為直接引用瓶殃。

可以考慮使用?-Xverify:none?參數(shù)來(lái)關(guān)閉大部分的類驗(yàn)證措施,以縮短虛擬機(jī)類加載的時(shí)間副签。

準(zhǔn)備

類變量分配內(nèi)存并設(shè)置類變量初始值遥椿,這些變量所使用的內(nèi)存都將在方法區(qū)中進(jìn)行分配。

解析

虛擬機(jī)將常量池內(nèi)的符號(hào)引用替換為直接引用的過(guò)程淆储。

解析動(dòng)作主要針對(duì)類或接口冠场、字段、類方法遏考、接口方法慈鸠、方法類型蓝谨、方法句柄和調(diào)用點(diǎn)限定符 7 類符號(hào)引用進(jìn)行灌具。

初始化

到初始化階段,才真正開始執(zhí)行類中定義的 Java 程序代碼譬巫,此階段是執(zhí)行?<clinit>()?方法的過(guò)程咖楣。

<clinit>()?方法是由編譯器按語(yǔ)句在源文件中出現(xiàn)的順序,依次自動(dòng)收集類中的所有類變量的賦值動(dòng)作和靜態(tài)代碼塊中的語(yǔ)句合并產(chǎn)生的芦昔。(不包括構(gòu)造器中的語(yǔ)句诱贿。構(gòu)造器是初始化對(duì)象的,類加載完成后,創(chuàng)建對(duì)象時(shí)候?qū)⒄{(diào)用的?<init>()?方法來(lái)初始化對(duì)象)

類加載的時(shí)機(jī)

對(duì)于初始化階段珠十,虛擬機(jī)規(guī)范規(guī)定了有且只有 5 種情況必須立即對(duì)類進(jìn)行“初始化”(而加載料扰、驗(yàn)證、準(zhǔn)備自然需要在此之前開始):

遇到new焙蹭、getstatic 和 putstatic 或 invokestatic 這4條字節(jié)碼指令時(shí)晒杈,如果類沒有進(jìn)行過(guò)初始化,則需要先觸發(fā)其初始化孔厉。對(duì)應(yīng)場(chǎng)景是:使用 new 實(shí)例化對(duì)象拯钻、讀取或設(shè)置一個(gè)類的靜態(tài)字段(被 final 修飾、已在編譯期把結(jié)果放入常量池的靜態(tài)字段除外)撰豺、以及調(diào)用一個(gè)類的靜態(tài)方法粪般。

對(duì)類進(jìn)行反射調(diào)用的時(shí)候,如果類沒有進(jìn)行過(guò)初始化污桦,則需要先觸發(fā)其初始化亩歹。

當(dāng)初始化類的父類還沒有進(jìn)行過(guò)初始化,則需要先觸發(fā)其父類的初始化凡橱。(而一個(gè)接口在初始化時(shí)捆憎,并不要求其父接口全部都完成了初始化)

虛擬機(jī)啟動(dòng)時(shí),用戶需要指定一個(gè)要執(zhí)行的主類(包含 main() 方法的那個(gè)類)梭纹,

虛擬機(jī)會(huì)先初始化這個(gè)主類躲惰。

當(dāng)使用 JDK 1.7 的動(dòng)態(tài)語(yǔ)言支持時(shí),如果一個(gè) java.lang.invoke.MethodHandle 實(shí)例最后的解析結(jié)果 REF_getStatic变抽、REF_putStatic础拨、REF_invokeStatic 的方法句柄,并且這個(gè)方法句柄所對(duì)應(yīng)的類沒有進(jìn)行過(guò)初始化绍载,則需要先觸發(fā)其初始化诡宗。

new一個(gè)對(duì)象過(guò)程中發(fā)生了什么?

確認(rèn)類元信息是否存在击儡。當(dāng) JVM 接收到 new 指令時(shí)塔沃,首先在 metaspace 內(nèi)檢查需要?jiǎng)?chuàng)建的類元信息是否存在。 若不存在阳谍,那么在雙親委派模式下蛀柴,使用當(dāng)前類加載器以 ClassLoader + 包名+類名為 Key 進(jìn)行查找對(duì)應(yīng)的 class 文件。 如果沒有找到文件矫夯,則拋出 ClassNotFoundException 異常 鸽疾, 如果找到,則進(jìn)行類加載(加載 - 驗(yàn)證 - 準(zhǔn)備 - 解析 - 初始化)训貌,并生成對(duì)應(yīng)的 Class 類對(duì)象制肮。

分配對(duì)象內(nèi)存冒窍。?首先計(jì)算對(duì)象占用空間大小,如果實(shí)例成員變量是引用變量豺鼻,僅分配引用變量空間即可综液,即 4 個(gè)字節(jié)大小,接著在堆中劃分—塊內(nèi)存給新對(duì)象儒飒。 在分配內(nèi)存空間時(shí)意乓,需要進(jìn)行同步操作,比如采用 CAS (Compare And Swap) 失敗重試约素、 區(qū)域加鎖等方式保證分配操作的原子性届良。

設(shè)定默認(rèn)值。?成員變量值都需要設(shè)定為默認(rèn)值圣猎, 即各種不同形式的零值士葫。

設(shè)置對(duì)象頭。設(shè)置新對(duì)象的哈希碼送悔、 GC 信息慢显、鎖信息、對(duì)象所屬的類元信息等欠啤。這個(gè)過(guò)程的具體設(shè)置方式取決于 JVM 實(shí)現(xiàn)荚藻。

執(zhí)行 init 方法。?初始化成員變量洁段,執(zhí)行實(shí)例化代碼塊应狱,調(diào)用類的構(gòu)造方法,并把堆內(nèi)對(duì)象的首地址賦值給引用變量祠丝。

10.jvm


jvm


JVM之常見的垃圾回收算法

算法一:引用計(jì)數(shù)法疾呻。

這個(gè)方法是最經(jīng)典點(diǎn)的一種方法。具體是對(duì)于對(duì)象設(shè)置一個(gè)引用計(jì)數(shù)器写半,每增加一個(gè)變量對(duì)它的引用岸蜗,引用計(jì)數(shù)器就會(huì)加1,沒減少一個(gè)變量的引用叠蝇,

?引用計(jì)數(shù)器就會(huì)減1璃岳,只有當(dāng)對(duì)象的引用計(jì)數(shù)器變成0時(shí),該對(duì)象才會(huì)被回收悔捶×蹇叮可見這個(gè)算法很簡(jiǎn)單,但是簡(jiǎn)單往往會(huì)存在很多問(wèn)題炎功,這里我列舉最明顯的兩個(gè)問(wèn)題枚冗,

1.是采用這種方法后缓溅,每次在增加變量引用和減少引用時(shí)都要進(jìn)行加法或減法操作蛇损,如果頻繁操作對(duì)象的話,在一定程度上增加的系統(tǒng)的消耗。

?2.是這種方法無(wú)法處理循環(huán)引用的情況淤齐。再解釋下什么是循環(huán)引用股囊,假設(shè)有兩個(gè)對(duì)象 A和B,A中引用了B對(duì)象更啄,并且B中也引用了A對(duì)象稚疹,那么這時(shí)兩個(gè)對(duì)象的引用計(jì)數(shù)器都不為0,但是由于存在相互引用導(dǎo)致無(wú)法垃圾回收A和 B祭务,導(dǎo)致內(nèi)存泄漏内狗。

算法二:標(biāo)記清除法。

這個(gè)方法是將垃圾回收分成了兩個(gè)階段:標(biāo)記階段和清除階段义锥。

在標(biāo)記階段柳沙,通過(guò)跟對(duì)象,標(biāo)記所有從跟節(jié)點(diǎn)開始的可達(dá)的對(duì)象拌倍,那么未標(biāo)記的對(duì)象就是未被引用的垃圾對(duì)象赂鲤。在清除階段,清除掉所以的未被標(biāo)記的對(duì)象柱恤。這個(gè)方法的缺點(diǎn)是数初,垃圾回收后可能存在大量的磁盤碎片,準(zhǔn)確的說(shuō)是內(nèi)存碎片梗顺。因?yàn)閷?duì)象所占用的地址空間是固定的泡孩。

算法三:標(biāo)記壓縮清除法(Java中老年代采用)

可以說(shuō)這個(gè)算法分為三個(gè)階段:標(biāo)記階段,壓縮階段寺谤,清除階段珍德。標(biāo)記階段和清除階段不變,只不過(guò)增加了一個(gè)壓縮階段矗漾,就是在做完標(biāo)記階段后锈候,

將這些標(biāo)記過(guò)的對(duì)象集中放到一起,確定開始和結(jié)束地址敞贡,比如全部放到開始處泵琳,這樣再去清除,將不會(huì)產(chǎn)生磁盤碎片誊役。但是我們也要注意到幾個(gè)問(wèn)題获列,壓縮階段占用了系統(tǒng)的消耗,并且如果標(biāo)記對(duì)象過(guò)多的話蛔垢,損耗可能會(huì)很大击孩,在標(biāo)記對(duì)象相對(duì)較少的時(shí)候,效率較高鹏漆。

算法四:復(fù)制算法(Java中新生代采用)巩梢。

核心思想是將內(nèi)存空間分成兩塊创泄,同一時(shí)刻只使用其中的一塊,在垃圾回收時(shí)將正在使用的內(nèi)存中的存活的對(duì)象復(fù)制到未使用的內(nèi)存中括蝠,然后清除正在使用的內(nèi)存塊中所有的對(duì)象鞠抑,然后把未使用的內(nèi)存塊變成正在使用的內(nèi)存塊,把原來(lái)使用的內(nèi)存塊變成未使用的內(nèi)存塊忌警。很明顯如果存活對(duì)象較多的話搁拙,算法效率會(huì)比較差,并且這樣會(huì)使內(nèi)存的空間折半法绵,但是這種方法也不會(huì)產(chǎn)生內(nèi)存碎片箕速。

算法五:分代法(Java堆采用)。

主要思想是根據(jù)對(duì)象的生命周期長(zhǎng)短特點(diǎn)將其進(jìn)行分塊朋譬,根據(jù)每塊內(nèi)存區(qū)間的特點(diǎn)弧满,使用不同的回收算法,從而提高垃圾回收的效率此熬。比如Java虛擬機(jī)中的堆就采用了這種方法分成了新生代和老年代庭呜。然后對(duì)于不同的代采用不同的垃圾回收算法。? 新生代使用了復(fù)制算法犀忱,老年代使用了標(biāo)記壓縮清除算法募谎。

算法六:分區(qū)算法。

這種方法將整個(gè)空間劃分成連續(xù)的不同的小區(qū)間阴汇,每個(gè)區(qū)間都獨(dú)立使用数冬,獨(dú)立回收,好處是可以控制一次回收多少個(gè)小區(qū)間搀庶。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末拐纱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子哥倔,更是在濱河造成了極大的恐慌秸架,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咆蒿,死亡現(xiàn)場(chǎng)離奇詭異东抹,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)沃测,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門缭黔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蒂破,你說(shuō)我怎么就攤上這事馏谨。” “怎么了附迷?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵惧互,是天一觀的道長(zhǎng)哎媚。 經(jīng)常有香客問(wèn)我,道長(zhǎng)壹哺,這世上最難降的妖魔是什么抄伍? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任艘刚,我火速辦了婚禮管宵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘攀甚。我一直安慰自己箩朴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布秋度。 她就那樣靜靜地躺著炸庞,像睡著了一般。 火紅的嫁衣襯著肌膚如雪荚斯。 梳的紋絲不亂的頭發(fā)上埠居,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音事期,去河邊找鬼滥壕。 笑死,一個(gè)胖子當(dāng)著我的面吹牛兽泣,可吹牛的內(nèi)容都是我干的绎橘。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼唠倦,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼称鳞!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起稠鼻,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤冈止,失蹤者是張志新(化名)和其女友劉穎衙传,沒想到半個(gè)月后姐扮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鳞芙,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡汪疮,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年羹膳,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了礁叔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拭荤。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡孟抗,死狀恐怖润匙,靈堂內(nèi)的尸體忽然破棺而出诗眨,到底是詐尸還是另有隱情,我是刑警寧澤孕讳,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布匠楚,位于F島的核電站巍膘,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏芋簿。R本人自食惡果不足惜峡懈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望与斤。 院中可真熱鬧肪康,春花似錦、人聲如沸撩穿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)食寡。三九已至雾狈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抵皱,已是汗流浹背善榛。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留呻畸,地道東北人移盆。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像擂错,于是被迫代替她去往敵國(guó)和親味滞。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容