面試系列之基礎篇

強引用 、軟引用、 弱引用、虛引用?

一般面試官會這樣問:你知道Java中對象的引用類型有哪幾種嗎?分別講講這幾種之間的區別?

強引用:只要強引用還存在,垃圾收集器永遠不會回收被引用的對象;

軟引用:描述一些還有用但是並非必需的對象,將要發生內存溢出之前,會被列進回收範圍之中進行第二次回收,如果在此次回收中還是沒有足夠的內存,就會拋出內存溢出異常(SoftReference);

弱引用:只能存活到下一次垃圾回收之前,當垃圾收集器回收時,無論當前內存是否足夠,被弱引用關聯的對象都會被回收掉;

虛引用:最弱的一個引用類型,完全不會影響其生存時間,可以理解爲沒有引用一樣,但是又有點區別,區別在於,弱引用關聯的對象在被收集器回收的時候能收到一個系統回收通知;

 

淺拷貝和深拷貝的區別?

淺拷貝:源對象和副本對象是同一個對象,源對象(副本對象)引用計數器+1,只是拷貝了源對象的引用;

深拷貝:源對象和副本對象是不同的兩個對象,源對象引用計數不變,副本對象計數器爲1,相當於重新開闢一塊內存生成一個新的對象;

 

Java中的值傳遞和引用傳遞?

值傳遞是指對象被值傳遞,意味着傳遞了對象的一個副本,即使副本被改變,也不會影響源對象;

引用傳遞,意味着傳遞的並不是實際的對象,而是對象的引用;

 

Java中覆蓋和重載的理解?

覆蓋(Override)是指子類對父類方法的一種重寫,只能比父類拋出更少的異常,訪問權限不能比父類的小;

重載(Overload)表示同一個類中可以有多個名稱相同的方法,但這些方法的參數列表各不相同;

那麼構成重載的條件有哪些?

參數類型不同、參數個數不同、參數順序不同;

函數的返回值不同可以構成重載嗎?

不可以,Java中調用函數並不需要強制賦值,根據方法的返回值是無法來區分重載方法的;

 

HashMap和Hashtable的區別?

HashMap沒有同步,是線程不安全的,Hashtable通過使用synchronized關鍵字來保證了線程安全;

HashMap允許null作爲key,而Hashtable是不允許的;

 

List 和 Set 的區別?

List:可以允許重複的對象、可以插入多個null元素

  • 有序容器,保持了每個元素的插入順序,輸出的順序就是插入的 順序
  • 常用的實現類有 ArrayList、LinkedList 和 Vector。ArrayList 最爲流行,它提供了使用索引的隨意訪問,而 LinkedList 則對於經常需要從 List 中添加或刪除元素的場合更爲合適

Set:不允許重複對象、只允許一個 null 元素

  • 無序容器,你無法保證每個元素的存儲順序,TreeSet通過 Comparator 或者 Comparable 維護了一個排序順序
  • Set 接口最流行的幾個實現類是 HashSet、LinkedHashSet 以及 TreeSet。最流行的是基於 HashMap 實現的 HashSet;TreeSet 還實現了 SortedSet 接口,因此 TreeSet 是一個根據其 compare() 和 compareTo() 的定義進行排序的有序容器

 

HashSet 是如何保證不重複的?

在向hashSet中add()元素時,判斷元素是否存在的依據,不僅僅是hash碼值就能夠確定的,同時還要結合equles方法:

  • 如果hash碼值不相同,說明是一個新元素,存

  • 如果hash碼值相同,且equles判斷相等,說明元素已經存在,不存

  • 如果hash碼值相同,且equles判斷不相等,說明元素不存在,存

 

ArrayList、LinkedList和HashMap默認空間是多少?什麼時候會擴容?如何擴容?

ArrayList:默認大小爲10;新增元素時發現容量不夠就會去擴容,擴容後的大小= 原始大小+原始大小/2 + 1;

LinkedList:雙向鏈表,沒有默認大小也沒有擴容機制;

HashMap:默認空間大小爲16,擴容因子爲0.75;噹噹前大小和當前容量 的比例超過了擴容因子,就會擴容,也就是說不會等到空間全部用完就會擴容,擴容後大小爲1倍即32,但是HashMap的擴容機制不是很友好,它是在存入數據之後進行判斷是否需要擴容,如果下次不會再有元素被存入,就會進行一次無效的擴容;

 

HashMap的底層原理了解嗎?

JDK1.8之前HashMap底層結構是數組+鏈表實現的,當hash碰撞嚴重的時候就會導致個別位置鏈表長度過長,從而影響性能;所以JDK1.8開始HashMap底層結構改爲數組+鏈表+紅黑樹實現,這樣也能避免多線程下HashMap死鎖的問題;

多線程會導致HashMap的Entry鏈表形成環形數據結構,一旦形成環,那麼Entry的next節點永遠不爲空,Hash就會陷入死循環獲取Entry的場景,從而發生HashMap死鎖;

 

ConcurrentHashMap和Hashtable的區別?

ConcurrentHashMap和Hashtable雖然都是線程安全的,但是有一些區別,Hashtable每次執行同步都是鎖住整個數據結構,而ConcurrentHashMap將Hash表分成16個段(segment),每次執行同步所影響的都是當前數據所在的段,不會導致整個hash全部鎖住,這種鎖的細粒度更小,效率更高;

那麼你知道ConcurrentHashMap底層具體是怎麼實現的嗎?

ConcurrentHashMap包含了兩個靜態內部類HashEntry和Segment,一個用來封裝映射表的鍵值對,另一個用來充當鎖的角色,Segment是一種可重入的鎖,每個Segment守護一個HashEntry數組裏的元素,當對HashEntry數組的數據進行修改時,必須先獲得對應的Segment鎖;

 

HashMap的長度爲什麼是2的冪次方?

HashMap是通過將Key的hash值與length-1進行&運算來實現Key的定位的,而2的冪次方可以減少hash衝突(碰撞)的次數,提高hashmap查詢效率,源碼如下:

// 返回key的座標,通過hash值以length-1做&運算
static int indexFor(int h, int length) {
       return h & (length-1);
   }

當length=2時的冪次方時,length-1轉化的二進制必定爲1111...(2的n次方實際就是1後面n個0,2的n次方-1  實際就是n個1)這種形式,在於hash值做&運算時效率會非常快,同時運算後的結果也是隨機分佈的,越隨機分佈hash衝突就越少;

當length!=2時的冪次方時,length-1和hash值做&運算,就會出現尾數永遠爲0的情況,這樣就會造成很多其他值永遠不會被entry佔用,增加了hash衝突的概率,也造成空間的浪費;

 

IO和NIO的區別?

IO面向流,NIO面向緩衝

IO阻塞,NIO非阻塞

IO無選擇器,NIO有選擇器(多路複用器)

兩種都是同步的,異步的IO爲AIO

 

什麼是隊列、棧、鏈表?

隊列:雙向管道,一邊進另一邊出,所以支持FIFO先進先出原則

棧:單向管道,那邊進那邊出,所以不支持FIFO,跟隊列相反,先進後出原則

鏈表:是一種線性表,由一系列結點組成,結點可以在運行時動態生成。每個節點包含一個存儲數據元素的數據域和一個指向下個節點的指針,通過指針形成鏈表,所以節點是可以空間上不連續的;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章