天天看點

2021年全網最全Java面試總結及答案【建議收藏】

37)怎樣通過 java 程式來判斷 jvm 是 32 位 還是 64 位?

======================================

你可以檢查某些系統屬性如 sun.arch.data.model 或 os.arch 來擷取該資訊。

38)32 位 jvm 和 64 位 jvm 的最大堆記憶體分别是多數?

===================================

理論上說上 32 位的 jvm 堆記憶體可以到達 2^32,即 4gb,但實際上會比這個小很多。不同作業系統之間不同,如 windows 系統大約 1.5 gb,solaris 大約 3gb。64 位 jvm允許指定最大的堆記憶體,理論上可以達到 2^64,這是一個非常大的數字,實際上你可以指定堆記憶體大小到 100gb。甚至有的 jvm,如 azul,堆記憶體到 1000g 都是可能的。

39)jre、jdk、jvm 及 jit 之間有什麼不同?

=============================

jre 代表 java 運作時(java run-time),是運作 java 應用所必須的。jdk 代表 java 開發工具(java development kit),是 java 程式的開發工具,如 java 編譯器,它也包含 jre。jvm 代表 java 虛拟機(java virtual machine),它的責任是運作 java 應用。jit 代表即時編譯(just in time compilation),當代碼執行的次數超過一定的門檻值時,會将 java 位元組碼轉換為本地代碼,如,主要的熱點代碼會被準換為本地代碼,這樣有利大幅度提高 java 應用的性能。

2021年全網最全Java面試總結及答案【建議收藏】

3 年工作經驗的 java 面試題

=================

40)解釋 java 堆空間及 gc?

===================

當通過 java 指令啟動 java 程序的時候,會為它配置設定記憶體。記憶體的一部分用于建立堆空間,當程式中建立對象的時候,就從對空間中配置設定記憶體。gc 是 jvm 内部的一個程序,回收無效對象的記憶體用于将來的配置設定。

jvm 底層面試題及答案

============

41)你能保證 gc 執行嗎?

===============

不能,雖然你可以調用 system.gc() 或者 runtime.getruntime().gc(),但是沒有辦法保證 gc 的執行。

42)怎麼擷取 java 程式使用的記憶體?堆使用的百分比?

可以通過 java.lang.runtime 類中與記憶體相關方法來擷取剩餘的記憶體,總記憶體及最大堆記憶體。通過這些方法你也可以擷取到堆使用的百分比及堆記憶體的剩餘空間。runtime.freememory() 方法傳回剩餘空間的位元組數,runtime.totalmemory() 方法總記憶體的位元組數,runtime.maxmemory() 傳回最大記憶體的位元組數。

43)java 中堆和棧有什麼差別?

==================

jvm 中堆和棧屬于不同的記憶體區域,使用目的也不同。棧常用于儲存方法幀和局部變量,而對象總是在堆上配置設定。棧通常都比堆小,也不會在多個線程之間共享,而堆被整個 jvm 的所有線程共享。difference between stack and heap memory in java

關于記憶體的的面試問題和答案

=============

java 基本概念面試題

44)“a==b”和”a.equals(b)”有什麼差別?

如果 a 和 b 都是對象,則 a==b 是比較兩個對象的引用,隻有當 a 和 b 指向的是堆中的同一個對象才會傳回 true,而 a.equals(b) 是進行邏輯比較,是以通常需要重寫該方法來提供邏輯一緻性的比較。例如,string 類重寫 equals() 方法,是以可以用于兩個不同對象,但是包含的字母相同的比較。

45)a.hashcode() 有什麼用?與 a.equals(b) 有什麼關系?

=========================================

hashcode() 方法是相應對象整型的 hash 值。它常用于基于 hash 的集合類,如 hashtable、hashmap、linkedhashmap等等。它與 equals() 方法關系特别緊密。根據 java 規範,兩個使用 equal() 方法來判斷相等的對象,必須具有相同的 hash code。

46)final、finalize 和 finally 的不同之處?

==================================

final 是一個修飾符,可以修飾變量、方法和類。如果 final 修飾變量,意味着該變量的值在初始化後不能被改變。java 技術允許使用 finalize() 方法在垃圾收集器将對象從記憶體中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在确定這個對象沒有被引用時對這個對象調用的,但是什麼時候調用 finalize 沒有保證。finally 是一個關鍵字,與 try 和 catch 一起用于異常的處理。finally 塊一定會被執行,無論在 try 塊中是否有發生異常。

47)java 中的編譯期常量是什麼?使用它又什麼風險?

============================

公共靜态不可變(public static final )變量也就是我們所說的編譯期常量,這裡的 public 可選的。實際上這些變量在編譯時會被替換掉,因為編譯器知道這些變量的值,并且知道這些變量在運作時不能改變。這種方式存在的一個問題是你使用了一個内部的或第三方庫中的公有編譯時常量,但是這個值後面被其他人改變了,但是你的用戶端仍然在使用老的值,甚至你已經部署了一個新的jar。為了避免這種情況,當你在更新依賴 jar 檔案時,確定重新編譯你的程式。

java 集合架構的面試題

這部分也包含資料結構、算法及數組的面試問題

48) list、set、map 和 queue 之間的差別(答案)

list 是一個有序集合,允許元素重複。它的某些實作可以提供基于下标值的常量通路時間,但是這不是 list 接口保證的。set 是一個無序集合。

49)poll() 方法和 remove() 方法的差別?

poll() 和 remove() 都是從隊列中取出一個元素,但是 poll() 在擷取元素失敗的時候會傳回空,但是 remove() 失敗的時候會抛出異常。

50)java 中 linkedhashmap 和 priorityqueue 的差別是什麼?(答案)

===================================================

priorityqueue 保證最高或者最低優先級的的元素總是在隊列頭部,但是 linkedhashmap 維持的順序是元素插入的順序。當周遊一個 priorityqueue 時,沒有任何順序保證,但是 linkedhashmap 課保證周遊順序是元素插入的順序。

51)arraylist 與 linkedlist 的不差別?(答案)

最明顯的差別是 arrraylist 底層的資料結構是數組,支援随機通路,而 linkedlist 的底層資料結構書連結清單,不支援随機通路。使用下标通路一個元素,arraylist 的時間複雜度是 o(1),而 linkedlist 是 o(n)。更多細節的讨論參見答案。

52)用哪兩種方式來實作集合的排序?(答案)

======================

你可以使用有序集合,如 treeset 或 treemap,你也可以使用有順序的的集合,如 list,然後通過 collections.sort() 來排序。

53)java 中怎麼列印數組?(answer答案)

==========================

你可以使用 arrays.tostring() 和 arrays.deeptostring() 方法來列印數組。由于數組沒有實作 tostring() 方法,是以如果将數組傳遞給 system.out.println() 方法,将無法列印出數組的内容,但是 arrays.tostring() 可以列印每個元素。

54)java 中的 linkedlist 是單向連結清單還是雙向連結清單?(答案)

是雙向連結清單,你可以檢查 jdk 的源碼。在 eclipse,你可以使用快捷鍵 ctrl + t,直接在編輯器中打開該類。

55)java 中的 treemap 是采用什麼樹實作的?(答案)

=================================

java 中的 treemap 是使用紅黑樹實作的。

56) hashtable 與 hashmap 有什麼不同之處?(答案)

====================================

這兩個類有許多不同的地方,下面列出了一部分:a) hashtable 是 jdk 1 遺留下來的類,而 hashmap 是後來增加的。b)hashtable 是同步的,比較慢,但 hashmap 沒有同步政策,是以會更快。c)hashtable 不允許有個空的 key,但是 hashmap 允許出現一個 null key。更多的不同之處參見答案。

57)java 中的 hashset,内部是如何工作的?(answer答案)

hashset 的内部采用 hashmap來實作。由于 map 需要 key 和 value,是以所有 key 的都有一個預設 value。類似于 hashmap,hashset 不允許重複的 key,隻允許有一個null key,意思就是 hashset 中隻允許存儲一個 null 對象。

58)寫一段代碼在周遊 arraylist 時移除一個元素?(答案)

該問題的關鍵在于面試者使用的是 arraylist 的 remove() 還是 iterator 的 remove()方法。這有一段示例代碼,是使用正确的方式來實作在周遊的過程中移除元素,而不會出現

concurrentmodificationexception 異常的示例代碼。

59)我們能自己寫一個容器類,然後使用 for-each 循環嗎?

可以,你可以寫一個自己的容器類。如果你想使用 java 中增強的循環來周遊,你隻需要實作 iterable 接口。如果你實作 collection 接口,預設就具有該屬性。

60)arraylist 和 hashmap 的預設大小是多數?(答案)

在 java 7 中,arraylist 的預設大小是 10 個元素,hashmap 的預設大小是16個元素(必須是2的幂)。這就是 java 7 中 arraylist 和 hashmap 類的代碼片段:

// from arraylist.java jdk 1.7

private static final int default_capacity = 10;

//from hashmap.java jdk 7

static final int default_initial_capacity = 1 << 4; // aka 16

複制代碼

61)有沒有可能兩個不相等的對象有有相同的 hashcode?

===============================

有可能,兩個不相等的對象可能會有相同的 hashcode 值,這就是為什麼在 hashmap 中會有沖突。相等 hashcode 值的規定隻是說如果兩個對象相等,必須有相同的hashcode 值,但是沒有關于不相等對象的任何規定。

62)兩個相同的對象會有不同的的 hash code 嗎?

不能,根據 hash code 的規定,這是不可能的。

63)我們可以在 hashcode() 中使用随機數字嗎?(答案)

不行,因為對象的 hashcode 值必須是相同的。參見答案擷取更多關于 java 中重寫 hashcode() 方法的知識。

64)java 中,comparator 與 comparable 有什麼不同?(答案)

============================================

comparable 接口用于定義對象的自然順序,而 comparator 通常用于定義使用者定制的順序。comparable 總是隻有一個,但是可以有多個 comparator 來定義對象的順序。

65)為什麼在重寫 equals 方法的時候需要重寫 hashcode 方法?(答案)

===========================================

因為有強制的規範指定需要同時重寫

hashcode 與 equal 是方法,許多容器類,如 hashmap、hashset 都依賴于 hashcode 與 equals 的規定。

java io 和 nio 的面試題

io 是 java 面試中一個非常重要的點。你應該很好掌握 java io,nio,nio2 以及與作業系統,磁盤 io 相關的基礎知識。下面是 java io 中經常問的問題。

66)在我 java 程式中,我有三個 socket,我需要多少個線程來處理?

=======================================

67)java 中怎麼建立 bytebuffer?

=========================

68)java 中,怎麼讀寫 bytebuffer ?

===========================

69)java 采用的是大端還是小端?

70)bytebuffer 中的位元組序是什麼?

=======================

71)java 中,直接緩沖區與非直接緩沖器有什麼差別?

72)java 中的記憶體映射緩存區是什麼?

=====================

73)socket 選項 tcp no delay 是指什麼?

74)tcp 協定與 udp 協定有什麼差別?

75)java 中,bytebuffer 與 stringbuffer有什麼差別?

java 最佳實踐的面試問題

==============

包含 java 中各個部分的最佳實踐,如集合,字元串,io,多線程,錯誤和異常處理,設計模式等等。

76)java 中,編寫多線程程式的時候你會遵循哪些最佳實踐?(答案)

這是我在寫java 并發程式的時候遵循的一些最佳實踐:a)給線程命名,這樣可以幫助調試。b)最小化同步的範圍,而不是将整個方法同步,隻對關鍵部分做同步。c)如果可以,更偏向于使用 volatile 而不是 synchronized。d)使用更高層次的并發工具,而不是使用 wait() 和 notify() 來實作線程間通信,如 blockingqueue,countdownlatch 及 semeaphore。e)優先使用并發集合,而不是對集合進行同步。并發集合提供更好的可擴充性。

77)說出幾點 java 中使用 collections 的最佳實踐(答案)

這是我在使用 java 中 collectionc 類的一些最佳實踐:

a)使用正确的集合類,例如,如果不需要同步清單,使用 arraylist 而不是 vector。

b)優先使用并發集合,而不是對集合進行同步。并發集合提供更好的可擴充性。

c)使用接口代表和通路集合,如使用list存儲 arraylist,使用 map 存儲 hashmap 等等。

d)使用疊代器來循環集合。e)使用集合的時候使用泛型。

78)說出至少 5 點在 java 中使用線程的最佳實踐。

這個問題與之前的問題類似,你可以使用上面的答案。 對線程來說,你應該:

a)對線程命名

b)将線程和任務分離,使用線程池執行器來執行 runnable 或 callable。

c)使用線程池

79)說出 5 條 io 的最佳實踐

io 對 java 應用的性能非常重要。理想情況下,你不應該在你應用的關鍵路徑上避免 io 操作。下面是一些你應該遵循的 java io 最佳實踐:

a)使用有緩沖區的 io 類,而不要單獨讀取位元組或字元。

b)使用 nio 和 nio2

c)在 finally 塊中關閉流,或者使用 try-with-resource(java7) 語句。

d)使用記憶體映射檔案擷取更快的 io。

80)列出 5 個應該遵循的 jdbc 最佳實踐

========================

有很多的最佳實踐,你可以根據你的喜好來例舉。

下面是一些更通用的原則:

a)使用批量的操作來插入和更新資料

b)使用 preparedstatement 來避免 sql 異常,并提高性能。

c)使用資料庫連接配接池

d)通過列名來擷取結果集,不要使用列的下标來擷取。

81)說出幾條 java 中方法重載的最佳實踐?

下面有幾條可以遵循的方法重載的最佳實踐來避免造成自動裝箱的混亂。

a)不要重載這樣的方法:一個方法接收 int 參數,而另個方法接收 integer 參數。

b)不要重載參數數量一緻,而隻是參數順序不同的方法。

c)如果重載的方法參數個數多于 5 個,采用可變參數。

date、time 及 calendar 的面試題

82)在多線程環境下,simpledateformat 是線程安全的嗎?

不是,非常不幸,dateformat 的所有實作,包括 simpledateformat 都不是線程安全的,是以你不應該在多線程式中使用,除非是在對外線程安全的環境中使用,如 将 simpledateformat 限制在 threadlocal 中。如果你不這麼做,在解析或者格式化日期的時候,可能會擷取到一個不正确的結果。是以,從日期、時間處理的所有實踐來說,我強力推薦 joda-time 庫。

83)java 中如何格式化一個日期?如格式化為 ddmmyyyy 的形式?

java 中,可以使用 simpledateformat 類或者 joda-time 庫來格式日期。dateformat 類允許你使用多種流行的格式來格式化日期。參見答案中的示例代碼,代碼中示範了将日期格式化成不同的格式,如 dd-mm-yyyy 或 ddmmyyyy。

84)java 中,怎麼在格式化的日期中顯示時區?

pattern中加z yyyy-mm-dd hh:mm:ss.sss z

85)java 中 java.util.date 與 java.sql.date 有什麼差別?

===============================================

java.sql.date是針對sql語句使用的,它隻包含日期而沒有時間部分,它們都有gettime方法傳回毫秒數,自然就可以直接建構。java.util.date 是 java.sql.date 的父類,前者是常用的表示時間的類,我們通常格式化或者得到目前時間都是用他,後者之後在讀寫資料庫的時候用他,因為preparedstament的setdate()的第2參數和resultset的getdate()方法的第2個參數都是java.sql.date。

86)java 中,如何計算兩個日期之間的差距?

public static int datediff(date d1, date d2) throws exception

{

long n1 = d1.gettime();long n2 = d2.gettime();

long diff = math.abs(n1 - n2);

diff /= 3600 1000 24;

return diff;

}

87)java 中,如何将字元串 yyyymmdd 轉換為日期?

================================

simpledateformat的parse方法

單元測試 junit 面試題

89)如何測試靜态方法?

可以使用 powermock 庫來測試靜态方法。

90)怎麼利用 junit 來測試一個方法的異常?

91)你使用過哪個單元測試庫來測試你的 java 程式?

92)@before 和 @beforeclass 有什麼差別?

程式設計和代碼相關的面試題

===========

93)怎麼檢查一個字元串隻包含數字?(解決方案)

94)java 中如何利用泛型寫一個 lru 緩存?(答案)

95)寫一段 java 程式将 byte 轉換為 long?(答案)

95)在不使用 stringbuffer 的前提下,怎麼反轉一個字元串?(解決方案)

97)java 中,怎麼擷取一個檔案中單詞出現的最高頻率?(解決方案)

98)如何檢查出兩個給定的字元串是反序的?(解決方案)

99)java 中,怎麼列印出一個字元串的所有排列?(解決方案)

100)java 中,怎樣才能列印出數組中的重複元素?(解決方案)

101)java 中如何将字元串轉換為整數?(解決方案)

102)在沒有使用臨時變量的情況如何交換兩個整數變量的值?(解決方案)

交換兩個值,不用臨時變量?我們通過位運算中的異或來實作。 //測試代碼為c語言代碼

前置知識:

1.一個整數自己跟自己異或,結果為0 //因為異或的法則為,相同為0,不同為1,注意這裡所說的都是二進制位。

2.任意一個整數跟0異或,結果為本身。//因為1異或0得1,0異或0,得0,是以1還是1,0還是0,沒發生變化。

測試代碼如下:

int main(int argc, char* argv[])

int a=575,b=667;

a=a^b;

b=a^b;

printf("a=%d b=%d \n",a,b);

getchar();

return 0;

//效果截圖如下:

2021年全網最全Java面試總結及答案【建議收藏】

分析下a和b發生交換的原因:

根據以上代碼不難得出以下表達式:

b=(a^b)^b=a^b^b=a

a=(a^b)^[(a^b)^b]=a^b^[a^b^b]=a^b^a^b^b=a^a^b^b^b=b

根據前面說的前置知識,不難明白a和b,為什麼發生交換了。

關于 oop 和設計模式的面試題

================

這部分包含 java 面試過程中關于 solid 的設計原則,oop 基礎,如類,對象,接口,繼承,多态,封裝,抽象以及更進階的一些概念,如組合、聚合及關聯。也包含了 gof 設計模式的問題。

103)接口是什麼?為什麼要使用接口而不是直接使用具體類?

接口用于定義 api。它定義了類必須得遵循的規則。同時,它提供了一種抽象,因為用戶端隻使用接口,這樣可以有多重實作,如 list 接口,你可以使用可随機通路的 arraylist,也可以使用友善插入和删除的 linkedlist。接口中不允許寫代碼,以此來保證抽象,但是 java 8 中你可以在接口聲明靜态的預設方法,這種方法是具體的。

104)java 中,抽象類與接口之間有什麼不同?(答案)

java 中,抽象類和接口有很多不同之處,但是最重要的一個是 java 中限制一個類隻能繼承一個類,但是可以實作多個接口。抽象類可以很好的定義一個家族類的預設行為,而接口能更好的定義類型,有助于後面實作多态機制。關于這個問題的讨論請檢視答案。

105)除了單例模式,你在生産環境中還用過什麼設計模式?

這需要根據你的經驗來回答。一般情況下,你可以說依賴注入,工廠模式,裝飾模式或者觀察者模式,随意選擇你使用過的一種即可。不過你要準備回答接下的基于你選擇的模式的問題。

106)你能解釋一下裡氏替換原則嗎?(答案)

107) 什麼情況下會違反迪米特法則?為什麼會有這個問題?(答案)

迪米特法則建議“隻和朋友說話,不要陌生人說話”,以此來減少類之間的耦合。

108)擴充卡模式是什麼?什麼時候使用?

====================

擴充卡模式提供對接口的轉換。如果你的用戶端使用某些接口,但是你有另外一些接口,你就可以寫一個适配去來連接配接這些接口。

109)什麼是“依賴注入”和“控制反轉”?為什麼有人使用?(答案)

110)抽象類是什麼?它與接口有什麼差別?你為什麼要使用過抽象類?(答案)

=====================================

抽象方法:由abstract修飾的方法為抽象方法,抽象方法隻有方法的定義,沒有方法的實作。 抽象類:一個類中如果包含抽象方法,個i類應該用abstract關鍵字聲明為抽象類。 抽象類不可以執行個體化,即使一個類中沒有抽象方法,也可以将其定義為抽象類,同樣,該類不可以執行個體化。

抽象類的意義:

1,為子類提供一個公共的類型;

2,封裝子類中重複内容(成員變量和方法);

3,定義有抽象方法,子類雖然有不同的實作,但該方法的定義是一緻的。

抽象類和接口的差別: 抽象類:為了被子類繼承,為子類提供了同一的方法入口; 接口:定義了一個标準(特殊的抽象類)。

111)構造器注入和 setter 依賴注入,那種方式更好?

==============================

每種方式都有它的缺點和優點。構造器注入保證所有的注入都被初始化,但是 setter 注入提供更好的靈活性來設定可選依賴。如果使用 xml 來描述依賴,setter 注入的可讀寫會更強。經驗法則是強制依賴使用構造器注入,可選依賴使用 setter 注入。

112)依賴注入和工廠模式之間有什麼不同?

雖然兩種模式都是将對象的建立從應用的邏輯中分離,但是依賴注入比工程模式更清晰。通過依賴注入,你的類就是 pojo,它隻知道依賴而不關心它們怎麼擷取。使用工廠模式,你的類需要通過工廠來擷取依賴。是以,使用 di 會比使用工廠模式更容易測試。關于這個話題的更詳細讨論請參見答案。

113)擴充卡模式和裝飾器模式有什麼差別?

雖然擴充卡模式和裝飾器模式的結構類似,但是每種模式的出現意圖不同。擴充卡模式被用于橋接兩個接口,而裝飾模式的目的是在不修改類的情況下給類增加新的功能。

114)擴充卡模式和代理模式之前有什麼不同?

這個問題與前面的類似,擴充卡模式和代理模式的差別在于他們的意圖不同。由于擴充卡模式和代理模式都是封裝真正執行動作的類,是以結構是一緻的,但是擴充卡模式用于接口之間的轉換,而代理模式則是增加一個額外的中間層,以便支援配置設定、控制或智能通路。

115)什麼是模闆方法模式?

模闆方法提供算法的架構,你可以自己去配置或定義步驟。例如,你可以将排序算法看做是一個模闆。它定義了排序的步驟,但是具體的比較,可以使用 comparable 或者其語言中類似東西,具體政策由你去配置。列出算法概要的方法就是衆所周知的模闆方法。

116)什麼時候使用通路者模式?

通路者模式用于解決在類的繼承層次上增加操作,但是不直接與之關聯。這種模式采用雙派發的形式來增加中間層。

117)什麼時候使用組合模式?

組合模式使用樹結構來展示部分與整體繼承關系。它允許用戶端采用統一的形式來對待單個對象和對象容器。當你想要展示對象這種部分與整體的繼承關系時采用組合模式。

118)繼承群組合之間有什麼不同?

雖然兩種都可以實作代碼複用,但是組合比繼承共靈活,因為組合允許你在運作時選擇不同的實作。用組合實作的代碼也比繼承測試起來更加簡單。

119)描述 java 中的重載和重寫?

重載和重寫都允許你用相同的名稱來實作不同的功能,但是重載是編譯時活動,而重寫是運作時活動。你可以在同一個類中重載方法,但是隻能在子類中重寫方法。重寫必須要有繼承。

120)java 中,嵌套公共靜态類與頂級類有什麼不同?

類的内部可以有多個嵌套公共靜态類,但是一個 java 源檔案隻能有一個頂級公共類,并且頂級公共類的名稱與源檔案名稱必須一緻。

121) oop 中的 組合、聚合和關聯有什麼差別?

如果兩個對象彼此有關系,就說他們是彼此相關聯的。組合和聚合是面向對象中的兩種形式的關聯。組合是一種比聚合更強力的關聯。組合中,一個對象是另一個的擁有者,而聚合則是指一個對象使用另一個對象。如果對象 a 是由對象 b 組合的,則 a 不存在的話,b一定不存在,但是如果 a 對象聚合了一個對象 b,則即使 a 不存在了,b 也可以單獨存在。