隨便分享點不那麼常規的面試題(一)

1. 爲何HashMap容許key和value爲空,而Hashtable和ConcurrentHashMap不容許key和value爲空?

本題主要考察是否熟悉各類map的應用場景,若是隻說出key/value爲空無心義是不夠的,要能考慮到更根本的緣由java

直接緣由mysql

  • HashMap將null的hash值設置爲0,因此容許key和value爲空
  • Hashtable會檢測當value爲空時拋出NPE,同時在計算hash值時直接調用了key的hashcode方法,若是key爲空會拋出NPE
  • ConcurrentHashMap會檢測當key或value爲空時拋出NPE

根本緣由linux

  • HashMap是線程不安全的,因此在設計時能夠只考慮單線程執行場景。使用get(key)方法前想判斷一個key-value鍵值對是否存在於Map中時,能夠調用containsKey方法,該方法是根據是否存在索引節點來判斷的,因此value爲空也無所謂,又由於是單線程的,因此containsKey方法和get方法不會出現線程安全問題
  • Hashtable和ConcurrentHashMap是線程安全的,在設計時,默認使用場景是多線程下。若是容許value爲空,則用戶調用get(key)方法後返回null不能判斷是否存在對應的key-null鍵值對,須要額外使用containsKey來進行判斷,在多線程場景下須要用戶手動進行加鎖。爲了減小用戶使用的負擔,以及避免因爲誤使用帶來嚴重的後果,同時也考慮到key/value爲空也沒有太大的意義,因此就禁止key/value爲空

2. 講一下linux的awk命令

本題主要考察對linux的使用深度,屬於加分項,沒有用過awk至少要讓面試官知道你用過grep,若是都沒有用過的話,面試官會懷疑你是否有linux的使用經驗程序員

awk是一個文本分析工具,將文件逐行讀入,而後默認按空格進行切片,對切開的部分進行單獨分析面試

格式是awk [options] '{command}' filename,如awk '{print $1}' out.txt,其中$1表明第1列,awk會默認按照分隔符來切分每一行算法

分隔符也能夠經過在awk後使用-F來指定,如awk -F ':' '{ print $1 }' out.txtspring

3. 數據庫水平分表以後怎麼查詢

本題主要考察你是否有考慮過度表以後的事情,而不是僅僅背了幾道面試題,說出聚合操做後這道題基本就經過了sql

若是查詢單條記錄,能夠根據查詢條件和分表規則找到對應的表,而後進行查詢並返回結果數據庫

若是查詢多條記錄,則分開查詢,將全部查詢結果作聚合,將聚合後的結果返回編程

4. mysql中select *** from *** limit offset, rows會有什麼問題,怎麼解決

本題主要考察數據庫查詢優化的知識,至少要能給出兩種解決方案,並說出其各自的優缺點

存在問題:當offset很大時,查詢效率會下降,由於mysql並不能直接定位到offset處進行查詢,而是查詢前offset+rows行,而後只取後rows條數據,將前面的數據捨棄,因此效率會很低

解決方案:

  1. limit offset, rows刪去,使用where 主鍵 > offset limit rows代替,可是使用前提是沒有其餘where條件對數據進行過濾
  2. 在子查詢中查出索引,外層查詢根據索引來定位數據,前提也是不能有其餘where條件對數據進行過濾
  3. 若是偏移量超過記錄數的一半,則反序查詢,能夠保證偏移量不會超過記錄數的一半
  4. 限制limit的偏移量,不容許超過某個值
  5. 用額外的表記錄數據和頁數的關係,可是隻適用於每頁條數固定的狀況

5. Java中final的實現原理是什麼

本題主要考察一些語言層面上的知識,若是知道泛型是語法糖的話,這個問題也能很容易回答出來

Java中final和private、泛型同樣,都是一種編程約束,編譯器會檢查final修飾的變量是否被從新賦值等,在編譯後與普通變量沒有區別

8. Java是編譯型語言仍是解釋型語言,JVM是編譯器嗎,什麼是JIT?

本題主要考察對Java語言的熟悉程度,能所有說正確固然最好,至少也得要能說出JVM是解釋器,Java是解釋型語言

Java既是解釋型語言也是編譯型語言。Java代碼須要通過javac編譯器編譯成class文件,交給JVM進行解釋執行,爲了加快執行效率,同時Java引入JIT編譯技術(Just-in-Time Compile,即時編譯技術),將部分熱點代碼編譯成機器碼優化執行

7. 逃逸分析瞭解嗎

本題主要考察對Java優化技術的瞭解程度,屬於加分項,回答好的話能給面試官留下深入印象

Java引入JIT技術後,會將熱點代碼編譯成本地機器相關的機器碼,編譯時會進行相應的優化,逃逸分析就是JIT優化的基礎

一個對象在方法中被定義後,若是被外部方法所引用,好比經過參數傳遞給其餘方法,就叫作(方法)逃逸。一樣地,若是一個對象能被其餘線程訪問到,也叫作逃逸。逃逸分析就是來分析對象是否發生了逃逸,經過逃逸分析,Java編譯器能夠分析出一個對象的使用範圍

當JIT使用逃逸分析時,能夠執行相應的優化策略:

  • 同步省略/鎖消除:若是同步塊只能被一個線程所訪問,則加鎖是沒有必要的,在優化時,同步塊上的鎖會被省略
  • 對象分離/標量替換:若是一個對象不會發生逃逸,則將對象屬性的引用替換爲標量,從而避免建立對象
  • 棧上分配:將不會發生逃逸的對象直接在棧上分配內存,而不是堆中,這樣能夠省略垃圾回收的操做(實際上仍是使用標量替換來完成的,沒有真正實現棧上分配)

逃逸分析這項技術至今仍不成熟,沒法保證逃逸分析所提升的運行效率能超過它的性能損耗,可是逃逸分析依然是JIT編譯器優化技術中一個重要手段

8. TCP粘包問題了解過嗎,怎麼解決

本題主要考察對TCP協議的瞭解程度,能回答出來TCP這塊基本就不會再問了。通常TCP部分的問題深度由淺至深分別是:TCP/UDP區別 => 三次握手與四次揮手 => 流量控制和擁塞控制 => TCP優化技術與常見問題,必需要作好準備

粘包問題有兩種常見狀況:

  1. TCP協議爲了將包更有效地發送到對象,因此使用Nagle優化算法,將多個小數據包合併成大數據塊進行封包,由於TCP傳輸的數據是沒有邊界的,因此接收方會收到一個粘成一團的包
  2. 接收方沒有即時接收消息,致使接收方的TCP緩衝區存放了幾段數據,接收方的應用層就會收到不完整的數據

解決方案有兩種,一種是隻發送固定長度的包,另外一種是在發送消息時帶上消息的長度,同時使用特殊標記來標記消息邊界

9. 爲何主鍵索引最好是自增的

本題考察的是你的思考能力,若是這題答得很差會給面試官留下只會背題的印象,此題不難,即便不知道答案只要給出本身的想法便可,重點是聯繫到索引的數據結構上

由於innodb索引採用b+樹的結構存儲,避免插入非規律主鍵的數據時,致使頁分裂

10. 接口和抽象方法哪個調用速度快,爲何

本題考察對JVM知識的掌握程度,雖然本題應用意義不大,可是能很好地考察出被面試者對JVM底層原理的瞭解狀況

抽象方法調用速度快,由於抽象類屬於實現類的父類,抽象方法的實現屬於方法覆寫,能夠直接根據偏移量來定位方法,而接口則只能經過遍從來找

11. 看下面這段代碼,執行結果是什麼,爲何

String a1 = new String("a") + new String("a");  // 1
        a1.intern();                                    // 2
        String a2 = "aa";                               // 3
        
        System.out.println(a1 == a2);

        // -------------------------------------
        
        String b1 = new String("b") + new String("b");  // 4 
        String b2 = "bb";                               // 5
        b1.intern();                                    // 6
        
        System.out.println(b1 == b2);
複製代碼

本題考察的是面試者對String的理解深度,此題的要點就是能答出intern方法的實現原理,可以徹底答對很是難,基本能打趴絕大多數面試者,可以回答出來講明對JVM的常量池很熟悉,絕對是一個加分項,不過遺憾的是基本沒有面試官會問這麼深

在jdk1.7以前,返回false false[1],在jdk1.7及以後的jdk版本中,返回true false

爲何在jdk1.7以前返回false false

  • 由於在jdk1.6中,字符串常量池在「永久代」中,調用String#intern方法時,若是常量池中已經存在該字符串對象,會直接返回常量池中的對象引用;不然會在常量池中建立一個對象,並返回常量池中對象的引用
  • 回到代碼中,代碼1在堆中建立了「aa」字符串對象,池中沒有「aa」字符串對象;代碼2發現常量池中沒有「aa」對象,則在池中建立「aa」對象;代碼3發現池中存在「aa」對象,直接返回常量池中對象的引用;此時,a1爲堆中字符串對象引用,a2爲常量池中字符串對象引用,顯然指向的不是同一個對象
  • 代碼4在堆中建立了「bb」字符串對象,池中沒有「bb」字符串對象;代碼5發現池中沒有「bb」對象,則在池中建立「bb」對象;代碼6發現常量池中存在「bb」對象,不執行操做;此時,b1爲堆中字符串對象引用,b2爲常量池中字符串對象引用,顯然指向的不是同一個對象

爲何在jdk1.7及以後返回true false

  • 在jdk1.7中,常量池被存放在Java堆中,jdk1.8中,常量池被放在元空間中,與堆獨立(其實主要跟intern方法的實現改變有關,和常量池在哪沒有太大關係,因此別被誤導了,這一點只是作個知識擴展)
  • 當調用String#intern方法時,若是常量池中已經有該對象,則返回常量池中對象的引用;不然,將Java堆中的對象引用添加到常量池中,並返回該引用;若是Java堆中也不存在,則在常量池中建立該字符串對象,並返回其引用
  • 回到代碼中,代碼1在堆中建立了「aa」字符串對象,池中沒有「aa」字符串對象;代碼2發現常量池中不存在「aa」對象,則檢查Java堆,發現存在「aa」對象,則將堆中該對象的引用添加到常量池中;代碼3發現常量池中存在「aa」對象的引用,則返回該引用;此時,a1爲堆中對象的引用,a2也爲堆中該對象的引用,指向的是同一對象
  • 代碼4/5/6與jdk1.6中的原理徹底一致,就再也不贅述了

12. ConcurrentHashMap的擴容是如何實現的

本題考察的是對ConcurrentHashMap源碼熟悉程度,答題要點是分區間處理和單節點加鎖。若是是考察HashMap的擴容,則答題要點是先建立新數組,再拷貝原數據

  1. 根據處理器個數,計算出每一個處理器要處理的區間個數
  2. 建立一個新數組
  3. 計算每一個線程須要處理的區間段大小
  4. 遍歷每一個索引位置,遍歷到時對索引節點單個進行加鎖
    1. 將索引位置下全部節點分爲兩個鏈表,一個是擴容後位置不變的,一個是擴容後位置改變的
    2. 處理完成後將這兩個鏈表一次性放置到原數組對應位置上(使用原子賦值操做,不會影響線程安全)

13. Service Mesh/Serverless是什麼

本題主要考察面試者的技術視野,是否僅僅關注本身眼前的技術。這種就屬於概念性的問題,能說多少說多少,沒有標準答案,能體現出本身有了解過大體的概念便可。這兩個問題自己沒有太大關聯,可是由於都屬於這一類問題,不想再單獨列出來,就直接放在一塊兒了

  • Service Mesh,指服務網格,屬於基礎設施層,功能在於處理服務間通訊,是系統通訊的中間層,負責實現請求的可靠傳遞。Service Mesh通常由一系列輕量級的網絡代理組成,和應用程序部署在一塊兒,可是對應用程序透明(不可見)。能夠解耦應用程序的重試、超時、監控、追蹤,以及服務發現,讓應用服務專一於業務邏輯
  • Serverless,指無服務架構,可讓開發者不用考慮服務器的問題,將計算資源做爲服務,而不是服務器。Serverless是一種構建和管理基於微服務架構的完整流程,容許開發者將應用以服務的級別來部署,而不是服務器級別。能夠不用去關心服務器運行狀態,不用考慮運營維護問題

14. 靜態方法和單例模式有什麼區別,咱們爲何推薦使用單例模式

本題主要考察面試者是否對本身使用的工具備過思考,可以知道「爲何用」,一個工程師至少要清楚本身使用工具的場景,而不能是稀裏糊塗的「有就用」

  1. 單例模式契合面向對象的思想
  2. 單例類中的方法能夠繼承覆寫
  3. 單例類能夠被延遲實例化
  4. 單例類能夠被用於多態,不須要關注全局的狀態

15. 僞共享瞭解嗎

本題考察的是面試者對線程安全(特指volatile部分)的掌握程度,若是認真看過JUC包下的源碼,就必定會了解到僞共享的概念。不過本題屬於加分項,即使不知道也沒有太大影響

僞共享指的是兩個volatile類型的數據在同一個緩存行中,因爲volatile每次都會刷新緩存行,因此致使緩存行沒有徹底發揮出做用,導致性能浪費

能夠經過在對象或字段的先後加padding,也可使用@sun.misc.Contended註解(其原理是在對象或字段先後加上128位的padding)

16. SpringBoot是怎麼啓動的

本題主要考察對Springboot的瞭解程度,答題要點是設置監聽器和加載上下文,若是這題沒答上來或沒答好面試官可能會問IoC和AOP原理相關的問題,因此至少有一個要很是熟悉

  • @SpringbootApplication複合了一些註解:
    • @SpringBootConfiguration:聲明該類爲配置類
    • @EnableAutoConfiguration:啓用自動配置,原理是使用AutoConfigurationImportSelector類,將全部配置類加載到容器中,並掃描配置文件,將配置項經過反射實例化爲配置類,彙總以後加載到容器中
    • @ComponentScan:自動掃描包下的bean
  • Springboot在啓動時,經過SpringApplication的run方法啓動容器。在run方法中,分爲兩步:
    1. 先構建SpringApplication對象,其中會設置成員變量和監聽器,最終推斷main方法所在的入口類
    1. 而後調用SpringApplication具體實例對象的run方法,會遍歷並啓動監聽器,封裝args參數爲對象,初始化並加載應用上下文

17. 適配器模式的應用場景是什麼,舉幾個具體應用的例子

本題主要考察對適配器這種設計模式的掌握程度,如今不少人爲了突擊面試,設計模式只看過單例和工廠兩種,若是問到其餘設計模式答不上來,會在面試官的心中大打折扣

應用場景:

  • 須要使用某個類,可是接口不符合須要
  • 須要將一些沒有公共接口/父類的類關聯起來,使其能夠一塊兒工做
  • 須要爲一些類提供統一的輸出接口

應用實例:

  • spring-aop:將不一樣的通知類型適配到統一的適配器接口AdvisorAdapter中,能夠經過具體的適配器類來獲取對應通知的攔截器
  • spring-mvc:使用HandlerAdapter來適配具體的Controller,實現了DispatcherServlet和Controller之間的統一接口對接

18. CountDownLatch的await()方法有什麼風險

本題主要考察面試者是否真正用過CountDownLatch,是否在使用時有考慮過風險。與此題相似的問題還有:ThreadLocal使用時須要注意什麼,SimpleDateFormat在多線程下使用有什麼風險等

若是執行countDown的線程發生異常,則await()方法會被阻塞。因此要設置超時時間,因此要使用await(timeout, unit)方法

19. 爲何有些公司棄用zookeeper

本題主要考察對zookeeper的掌握程度,能說出一種工具的優勢很容易,有時候編也能編個差很少,可是想說出來缺點就須要對它有至關的瞭解才行。若是是校招的話通常不會問這麼深,回答不上來也不用太緊張,可是必定要勇於說出來本身的看法,即便是錯的

客戶端:

  • 服務端集羣的地址列表是寫死在客戶端的,不支持動態變動
  • 不支持同機房優先策略
  • 沒有針對服務端集羣徹底不可用的容災策略

服務端:

  • 寫能力不足,不支持水平擴展
  • 監測手段單一,只有TCP的活性監測

20. Java中基本數據類型是對象嗎

本題考察的是對Java語言的理解程度,這個問題幾乎沒見過有面試官問過,問題自己的價值也不是很大,若是答不上來也沒有太大關係,不過確實能反應出面試者對語言的認識程度

JVM會把全部的基本數據類型看成對象處理,JVM有9種設定好的Class對象來對應基本數據類型void關鍵字,這些對象都是JVM建立的

除了基本類型以外,枚舉也是一種類,註解屬於一種特殊的接口,數組也是Object的子類,可是對程序員是透明的


  1. 勘誤:使用openjdk6測試發現輸出依然是true false,此題有待進一步研究 ↩︎

相關文章
相關標籤/搜索