2021年整理Java面試題初級+中級+高階-3
2021年整理Java面試題初級+中級+高階-3
先給大家複習一下基礎題!!!
Java基礎是java初學者的起點,是幫助你從小白入門到精通必學基礎課程!
為初學者而著!
配套學習:
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;
a=a^b;
printf("a=%d b=%d \n",a,b);
getchar();
return 0;
}
效果截圖如下:
分析下a和b發生交換的原因:
根據以上程式碼不難得出以下表達式:
1. b=(a^b)^b=a^b^b=a2. 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 也可以單獨存在。
122)給我一個符合開閉原則的設計模式的例子?
開閉原則要求你的程式碼對擴充套件開放,對修改關閉。這個意思就是說,如果你想增加一個新的功能,你可以很容易的在不改變已測試過的程式碼的前提下增加新的程式碼。有好幾個設計模式是基於開閉原則的,如策略模式,如果你需要一個新的策略,只需要實現介面,增加配置,不需要改變核心邏輯。一個正在工作的例子是 Collections.sort() 方法,這就是基於策略模式,遵循開閉原則的,你不需為新的物件修改 sort() 方法,你需要做的僅僅是實現你自己的 Comparator 介面。
123)抽象工廠模式和原型模式之間的區別?
124)什麼時候使用享元模式?
享元模式通過共享物件來避免建立太多的物件。為了使用享元模式,你需要確保你的物件是不可變的,這樣你才能安全的共享。JDK 中 String 池、Integer 池以及 Long 池都是很好的使用了享元模式的例子。
Java 面試中其他各式各樣的問題
這部分包含 Java 中關於 XML 的面試題,JDBC 面試題,正則表示式面試題,Java 錯誤和異常及序列化面試題
125)巢狀靜態類與頂級類有什麼區別?
一個公共的頂級類的原始檔名稱與類名相同,而巢狀靜態類沒有這個要求。一個巢狀類位於頂級類內部,需要使用頂級類的名稱來引用巢狀靜態類,如 HashMap.Entry 是一個巢狀靜態類,HashMap 是一個頂級類,Entry是一個巢狀靜態類。
126)你能寫出一個正則表示式來判斷一個字串是否是一個數字嗎?
一個數字字串,只能包含數字,如 0 到 9 以及 +、- 開頭,通過這個資訊,你可以下一個如下的正則表示式來判斷給定的字串是不是數字。
127)Java 中,受檢查異常 和 不受檢查異常的區別?
受檢查異常編譯器在編譯期間檢查。對於這種異常,方法強制處理或者通過 throws 子句宣告。其中一種情況是 Exception 的子類但不是 RuntimeException 的子類。非受檢查是 RuntimeException 的子類,在編譯階段不受編譯器的檢查。
128)Java 中,throw 和 throws 有什麼區別?
throw 用於丟擲 java.lang.Throwable 類的一個例項化物件,意思是說你可以通過關鍵字 throw 丟擲一個 Error 或者 一個Exception,如:throw new IllegalArgumentException(“size must be multiple of 2″) 而throws 的作用是作為方法宣告和簽名的一部分,方法被丟擲相應的異常以便呼叫者能處理。Java 中,任何未處理的受檢查異常強制在 throws 子句中宣告。
129)Java 中,Serializable 與 Externalizable 的區別?
Serializable 介面是一個序列化 Java 類的介面,以便於它們可以在網路上傳輸或者可以將它們的狀態儲存在磁碟上,是 JVM 內嵌的預設序列化方式,成本高、脆弱而且不安全。Externalizable 允許你控制整個序列化過程,指定特定的二進位制格式,增加安全機制。
130)Java 中,DOM 和 SAX 解析器有什麼不同?
DOM 解析器將整個 XML 文件載入到記憶體來建立一棵 DOM 模型樹,這樣可以更快的查詢節點和修改 XML 結構,而 SAX 解析器是一個基於事件的解析器,不會將整個 XML 文件載入到記憶體。由於這個原因,DOM 比 SAX 更快,也要求更多的記憶體,不適合於解析大 XML 檔案。
131)說出 JDK 1.7 中的三個新特性?
雖然 JDK 1.7 不像 JDK 5 和 8 一樣的大版本,但是,還是有很多新的特性,如 try-with-resource 語句,這樣你在使用流或者資源的時候,就不需要手動關閉,Java 會自動關閉。Fork-Join 池某種程度上實現 Java 版的 Map-reduce。允許 Switch 中有 String 變數和文字。菱形操作符(<>)用於型別推斷,不再需要在變數宣告的右邊申明泛型,因此可以寫出可讀寫更強、更簡潔的程式碼。另一個值得一提的特性是改善異常處理,如允許在同一個 catch 塊中捕獲多個異常。
132)說出 5 個 JDK 1.8 引入的新特性?
Java 8 在 Java 歷史上是一個開創新的版本,下面 JDK 8 中 5 個主要的特性:Lambda 表示式,允許像物件一樣傳遞匿名函式 Stream API,充分利用現代多核 CPU,可以寫出很簡潔的程式碼 Date 與 Time API,最終,有一個穩定、簡單的日期和時間庫可供你使用 擴充套件方法,現在,介面中可以有靜態、預設方法。重複註解,現在你可以將相同的註解在同一型別上使用多次。
133)Java 中,Maven 和 ANT 有什麼區別?
雖然兩者都是構建工具,都用於建立 Java 應用,但是 Maven 做的事情更多,在基於“約定優於配置”的概念下,提供標準的Java 專案結構,同時能為應用自動管理依賴(應用中所依賴的 JAR 檔案),Maven 與 ANT 工具更多的不同之處請參見答案。
小夥伴如果想要學習更多的知識,學習材料可以,工眾號:程式設計領域
Java初學者學習教程: