31道Java核心面試題,一次性打包送給你
二哥,你好,找工作找了仨月,還沒有找到,很焦慮,我該怎么辦呢?你那有沒有 Java 方面的面試題可以分享一波???
以上是讀者田田給我發(fā)的私信,看完后于我心有戚戚焉啊,最近境況確實不容樂觀,并非是個人的原因造成的。那,既然需要面試題,二哥就義不容辭,必須得準(zhǔn)備一波。
這次我花了一周的時間,準(zhǔn)備了 31 道 Java 核心面試題,希望能夠幫助到田田,以及其他和田田類似情況的讀者朋友。
01、請說出 Java 14 版本中更新的重要功能
Java 14 發(fā)布于 2020 年 3 月 17 日,更新的重要功能有:
- switch 表達(dá)式
- instanceof 增強表達(dá)式,預(yù)覽功能
- 文本塊,第二次預(yù)覽
- Records,預(yù)覽功能
剛好我之前寫過一篇文章,關(guān)于 Java 14 的開箱體驗,很香,讀者朋友需要的話,可以點下面的鏈接看一看。
Java 14 開箱,它真香香香香
02、請說出 Java 13 版本中更新的重要功能
Java 13 發(fā)布于 2019 年 9 月 17 日,更新的重要功能有:
- 文本塊,預(yù)覽功能
- switch 表達(dá)式,預(yù)覽功能
- Java Socket 重新實現(xiàn)
- FileSystems.newFileSystem() 方法
- 支持 Unicode 12.1
- 可伸縮、低延遲的垃圾收集器改進(jìn),用于返回未使用的內(nèi)存
03、請說出 Java 12 版本中更新的重要功能
Java 12 發(fā)布于 2019 年 3 月 19 日,更新的重要功能有:
- JVM 更新
- File.mismatch() 方法
- 緊湊型數(shù)字格式
- String 類新增了一些方法,比如說 indent()
04、請說出 Java 11 版本中更新的重要功能
Java 11 是繼 Java 8 之后的第二個商用版本,如果你下載的是 Oracle JDK,則需要進(jìn)行付費;如果想繼續(xù)使用免費版本,需要下載 Open JDK。
Oracle JDK 中會有一些 Open JDK 沒有的、商用閉源的功能。
Java 11 更新的重要功能有:
- 可以直接使用 java 命令運行 Java 程序,源代碼將會隱式編譯和運行。
- String 類新增了一些方法,比如說 isBlank()、lines()、strip() 等等。
- Files 類新增了兩個讀寫方法,readString() 和 writeString()。
- 可以在 Lambda 表達(dá)式中使用 var 作為變量類型。
05、請說出 Java 10 版本中更新的重要功能
Java 10 更新的重要功能有:
- 局部變量類型推斷,舉個例子,var list = new ArrayList();,可以使用 var 來作為變量類型,Java 編譯器知道 list 的類型為字符串的 ArrayList。
- 增強 java.util.Locale。
- 提供了一組默認(rèn)的根證書頒發(fā)機構(gòu)(CA)。
06、請說出 Java 9 版本中更新的重要功能
Java 9 更新的重要功能有:
- 模塊系統(tǒng)
- 不可變的 List、Set、Map 的工廠方法
- 接口中可以有私有方法
- 垃圾收集器改進(jìn)
07、請說出 Java 8 版本中更新的重要功能
Java 8 發(fā)布于 2014 年 3 月份,可以說是 Java 6 之后最重要的版本更新,深受開發(fā)者的喜愛。
- 函數(shù)式編程和 Lambda 表達(dá)式
- Stream 流
- Java Date Time API
- 接口中可以使用默認(rèn)方法和靜態(tài)方法
我強烈建議點開上面的鏈接閱讀以下,以正確理解這些概念。
08、請說出 Java 面向?qū)ο缶幊讨械囊恍┲匾拍?/strong>
- 抽象
- 封裝
- 多態(tài)
- 繼承
09、Java 聲稱的平臺獨立性指的是什么?
常見的操作系統(tǒng)有 Windows、Linux、OS-X,那么平臺獨立性意味著我們可以在任何操作系統(tǒng)中運行相同源代碼的 Java 程序,比如說我們可以在 Windows 上編寫 Java 程序,然后在 Linux 上運行它。
10、什么是 JVM?
JVM(Java Virtual Machine)俗稱 Java 虛擬機。之所以稱為虛擬機,是因為它實際上并不存在。它提供了一種運行環(huán)境,可供 Java 字節(jié)碼在上面運行。
JVM 提供了以下操作:
- 加載字節(jié)碼
- 驗證字節(jié)碼
- 執(zhí)行字節(jié)碼
- 提供運行時環(huán)境
JVM 定義了以下內(nèi)容:
- 存儲區(qū)
- 類文件格式
- 寄存器組
- 垃圾回收堆
- 致命錯誤報告等
我們來嘗試?yán)斫庖幌?JVM 的內(nèi)部結(jié)構(gòu),它包含了類加載器(Class Loader)、運行時數(shù)據(jù)區(qū)(Runtime Data Areas)和執(zhí)行引擎(Excution Engine)。
1)類加載器
類加載器是 JVM 的一個子系統(tǒng),用于加載類文件。每當(dāng)我們運行一個 Java 程序,它都會由類加載器首先加載。Java 中有三個內(nèi)置的類加載器:
- 啟動類加載器(Bootstrap Class-Loader),加載 jre/lib 包下面的 jar 文件,比如說常見的 rt.jar(包含了 Java 標(biāo)準(zhǔn)庫下的所有類文件,比如說 java.lang 包下的類,java.net 包下的類,java.util 包下的類,java.io 包下的類,java.sql 包下的類)。
- 擴展類加載器(Extension or Ext Class-Loader),加載 jre/lib/ext 包下面的 jar 文件。
- 應(yīng)用類加載器(Application or App Clas-Loader),根據(jù)程序的類路徑(classpath)來加載 Java 類。
一般來說,Java 程序員并不需要直接同類加載器進(jìn)行交互。JVM 默認(rèn)的行為就已經(jīng)足夠滿足大多數(shù)情況的需求了。不過,如果遇到了需要和類加載器進(jìn)行交互的情況,而對類加載器的機制又不是很了解的話,就不得不花大量的時間去調(diào)試
ClassNotFoundException 和 NoClassDefFoundError 等異常。
對于任意一個類,都需要由它的類加載器和這個類本身一同確定其在 JVM 中的唯一性。也就是說,如果兩個類的加載器不同,即使兩個類來源于同一個字節(jié)碼文件,那這兩個類就必定不相等(比如兩個類的 Class 對象不 equals)。
是不是有點暈,來來來,通過一段簡單的代碼了解下。
- public class Test {
- public static void main(String[] args) {
- ClassLoader loader = Test.class.getClassLoader();
- while (loader != null) {
- System.out.println(loader.toString());
- loaderloader = loader.getParent();
- }
- }
- }
每個 Java 類都維護(hù)著一個指向定義它的類加載器的引用,通過 類名.class.getClassLoader() 可以獲取到此引用;然后通過 loader.getParent() 可以獲取類加載器的上層類加載器。
上面這段代碼的輸出結(jié)果如下:
- sun.misc.Launcher$AppClassLoader@18b4aac2
- sun.misc.Launcher$ExtClassLoader@4617c264
第一行輸出為 Test 的類加載器,即應(yīng)用類加載器,它是 sun.misc.Launcher$AppClassLoader 類的實例;第二行輸出為擴展類加載器,是 sun.misc.Launcher$ExtClassLoader 類的實例。那啟動類加載器呢?
按理說,擴展類加載器的上層類加載器是啟動類加載器,但在我這個版本的 JDK 中, 擴展類加載器的 getParent() 返回 null。所以沒有輸出。
2)運行時數(shù)據(jù)區(qū)
運行時數(shù)據(jù)區(qū)又包含以下內(nèi)容。
- PC寄存器(PC Register),也叫程序計數(shù)器(Program Counter Register),是一塊較小的內(nèi)存空間,它的作用可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的信號指示器。
- JVM 棧(Java Virtual Machine Stack),與 PC 寄存器一樣,JVM 棧也是線程私有的。每一個 JVM 線程都有自己的 JVM 棧,這個棧與線程同時創(chuàng)建,它的生命周期與線程相同。
- 本地方法棧(Native Method Stack),JVM 可能會使用到傳統(tǒng)的棧來支持 Native 方法(使用 Java 語言以外的其它語言[C語言]編寫的方法)的執(zhí)行,這個棧就是本地方法棧。
- 堆(Heap),在 JVM 中,堆是可供各條線程共享的運行時內(nèi)存區(qū)域,也是供所有類實例和數(shù)據(jù)對象分配內(nèi)存的區(qū)域。
- 方法區(qū)(Method area),在 JVM 中,被加載類型的信息都保存在方法區(qū)中。包括類型信息(Type Information)和方法列表(Method Tables)。方法區(qū)是所有線程共享的,所以訪問方法區(qū)信息的方法必須是線程安全的。
- 運行時常量池(Runtime Constant Pool),運行時常量池是每一個類或接口的常量池在運行時的表現(xiàn)形式,它包括了編譯器可知的數(shù)值字面量,以及運行期解析后才能獲得的方法或字段的引用。簡而言之,當(dāng)一個方法或者變量被引用時,JVM 通過運行時常量區(qū)來查找方法或者變量在內(nèi)存里的實際地址。
3)執(zhí)行引擎
執(zhí)行引擎包含了:
- 解釋器:讀取字節(jié)碼流,然后執(zhí)行指令。因為它一條一條地解釋和執(zhí)行指令,所以它可以很快地解釋字節(jié)碼,但是執(zhí)行起來會比較慢。
- 即時(Just-In-Time,JIT)編譯器:即時編譯器用來彌補解釋器的缺點,提高性能。執(zhí)行引擎首先按照解釋執(zhí)行的方式來執(zhí)行,然后在合適的時候,即時編譯器把整段字節(jié)碼編譯成本地代碼。然后,執(zhí)行引擎就沒有必要再去解釋執(zhí)行方法了,它可以直接通過本地代碼去執(zhí)行。執(zhí)行本地代碼比一條一條進(jìn)行解釋執(zhí)行的速度快很多。編譯后的代碼可以執(zhí)行的很快,因為本地代碼是保存在緩存里的。
11、JDK 和 JVM 有什么區(qū)別?
JDK 是 Java Development Kit 的首字母縮寫,是提供給 Java 開發(fā)人員的軟件環(huán)境,包含 JRE 和一組開發(fā)工具。可分為以下版本:
- 標(biāo)準(zhǔn)版(大多數(shù)開發(fā)人員用的就是這個)
- 企業(yè)版
- 微型版
JDK 包含了一個私有的 JVM 和一些其他資源,比如說編譯器(javac 命令)、解釋器(java 命令)等,幫助 Java 程序員完成開發(fā)工作。
12、JVM 和 JRE 有什么區(qū)別?
Java Runtime Environment(JRE)是 JVM 的實現(xiàn)。JRE 由 JVM 和 Java 二進(jìn)制文件以及其他類組成,可以執(zhí)行任何程序。JRE 不包含 Java 編譯器,調(diào)試器等任何開發(fā)工具。
13、哪個類是所有類的超類?
java.lang.Object 是所有 Java 類的超類,我們不需要繼承它,因為是隱式繼承的。
14、為什么 Java 不支持多重繼承?
如果有兩個類共同繼承(extends)一個有特定方法的父類,那么該方法會被兩個子類重寫。然后,如果你決定同時繼承這兩個子類,那么在你調(diào)用該重寫方法時,編譯器不能識別你要調(diào)用哪個子類的方法。這也正是著名的菱形問題,見下圖。
ClassC 同時繼承了 ClassA 和 ClassB,ClassC 的對象在調(diào)用 ClassA 和 ClassB 中重載的方法時,就不知道該調(diào)用 ClassA 的方法,還是 ClassB 的方法。
15、為什么 Java 不是純粹的面向?qū)ο缶幊陶Z言?
之所以不能說 Java 是純粹的面向?qū)ο缶幊陶Z言,是因為 Java 支持基本數(shù)據(jù)類型,比如說 int、short、long、double 等,盡管它們有自己的包裝器類型,但它們的確不能算是對象。
16、path 和 classpath 之間有什么區(qū)別?
path 是操作系統(tǒng)用來查找可執(zhí)行文件的環(huán)境變量,我的電腦上就定義了下圖這些 path 變量,比如 Java 和 Maven 的。
classpath 是針對 Java 而言的,用于指定 Java 虛擬機載入的字節(jié)碼文件路徑。
17、Java 中 `main()` 方法的重要性是什么?
每個程序都需要一個入口,對于 Java 程序來說,入口就是 main 方法。
public static void main(String[] args) {}
- public 關(guān)鍵字是另外一個訪問修飾符,除了可以聲明方法和變量(所有類可見),還可以聲明類。main() 方法必須聲明為 public。
- static 關(guān)鍵字表示該變量或方法是靜態(tài)變量或靜態(tài)方法,可以直接通過類訪問,不需要實例化對象來訪問。
- void 關(guān)鍵字用于指定方法沒有返回值。
另外,main 關(guān)鍵字為方法的名字,Java 虛擬機在執(zhí)行程序時會尋找這個標(biāo)識符;args 為 main() 方法的參數(shù)名,它的類型為一個 String 數(shù)組,也就是說,在使用 java 命令執(zhí)行程序的時候,可以給 main() 方法傳遞字符串?dāng)?shù)組作為參數(shù)。
- java HelloWorld 沉默王二 沉默王三
javac 命令用來編譯程序,java 命令用來執(zhí)行程序,HelloWorld 為這段程序的類名,沉默王二和沉默王三為字符串?dāng)?shù)組,中間通過空格隔開,然后就可以在 main() 方法中通過 args[0] 和 args[1] 獲取傳遞的參數(shù)值了。
- public class HelloWorld {
- public static void main(String[] args) {
- if ("沉默王二".equals(args[0])) {
- }
- if ("沉默王三".equals(args[1])) {
- }
- }
- }
main() 方法的寫法并不是唯一的,還有其他幾種變體,盡管它們可能并不常見,可以簡單來了解一下。
第二種,把方括號 [] 往 args 靠近而不是 String 靠近:
- public static void main(String []args) { }
第三種,把方括號 [] 放在 args 的右側(cè):
- public static void main(String args[]) { }
第四種,還可以把數(shù)組形式換成可變參數(shù)的形式:
- public static void main(String...args) { }
第五種,在 main() 方法上添加另外一個修飾符 strictfp,用于強調(diào)在處理浮點數(shù)時的兼容性:
- public strictfp static void main(String[] args) { }
也可以在 main() 方法上添加 final 關(guān)鍵字或者 synchronized 關(guān)鍵字。
第六種,還可以為 args 參數(shù)添加 final 關(guān)鍵字:
- public static void main(final String[] args) { }
第七種,最復(fù)雜的一種,所有可以添加的關(guān)鍵字統(tǒng)統(tǒng)添加上:
- final static synchronized strictfp void main(final String[] args) { }
當(dāng)然了,并不需要為了裝逼特意把 main() 方法寫成上面提到的這些形式,使用 IDE 提供的默認(rèn)形式就可以了。
18、Java 的重寫(Override)和重載(Overload)有什么區(qū)別?
先來看一段重寫的代碼吧。
- class LaoWang{
- public void write() {
- System.out.println("老王寫了一本《基督山伯爵》");
- }
- }
- public class XiaoWang extends LaoWang {
- @Override
- public void write() {
- System.out.println("小王寫了一本《茶花女》");
- }
- }
重寫的兩個方法名相同,方法參數(shù)的個數(shù)也相同;不過一個方法在父類中,另外一個在子類中。就好像父類 LaoWang 有一個 write() 方法(無參),方法體是寫一本《基督山伯爵》;子類 XiaoWang 重寫了父類的 write() 方法(無參),但方法體是寫一本《茶花女》。
來寫一段測試代碼。
- public class OverridingTest {
- public static void main(String[] args) {
- LaoWang wang = new XiaoWang();
- wang.write();
- }
- }
大家猜結(jié)果是什么?
小王寫了一本《茶花女》
在上面的代碼中,們聲明了一個類型為 LaoWang 的變量 wang。在編譯期間,編譯器會檢查 LaoWang 類是否包含了 write() 方法,發(fā)現(xiàn) LaoWang 類有,于是編譯通過。在運行期間,new 了一個 XiaoWang 對象,并將其賦值給 wang,此時 Java 虛擬機知道 wang 引用的是 XiaoWang 對象,所以調(diào)用的是子類 XiaoWang 中的 write() 方法而不是父類 LaoWang 中的 write() 方法,因此輸出結(jié)果為“小王寫了一本《茶花女》”。
再來看一段重載的代碼吧。
- class LaoWang{
- public void read() {
- System.out.println("老王讀了一本《Web全棧開發(fā)進(jìn)階之路》");
- }
- public void read(String bookname) {
- System.out.println("老王讀了一本《" + bookname + "》");
- }
- }
重載的兩個方法名相同,但方法參數(shù)的個數(shù)不同,另外也不涉及到繼承,兩個方法在同一個類中。就好像類 LaoWang 有兩個方法,名字都是 read(),但一個有參數(shù)(書名),另外一個沒有(只能讀寫死的一本書)。
來寫一段測試代碼。
- public class OverloadingTest {
- public static void main(String[] args) {
- LaoWang wang = new LaoWang();
- wang.read();
- wang.read("金瓶梅");
- }
- }
這結(jié)果就不用猜了。變量 wang 的類型為 LaoWang,wang.read() 調(diào)用的是無參的 read() 方法,因此先輸出“老王讀了一本《Web全棧開發(fā)進(jìn)階之路》”;wang.read("金瓶") 調(diào)用的是有參的 read(bookname) 方法,因此后輸出“老王讀了一本《金瓶》”。在編譯期間,編譯器就知道這兩個 read() 方法時不同的,因為它們的方法簽名(=方法名稱+方法參數(shù))不同。
簡單的來總結(jié)一下:
1)編譯器無法決定調(diào)用哪個重寫的方法,因為只從變量的類型上是無法做出判斷的,要在運行時才能決定;但編譯器可以明確地知道該調(diào)用哪個重載的方法,因為引用類型是確定的,參數(shù)個數(shù)決定了該調(diào)用哪個方法。
2)多態(tài)針對的是重寫,而不是重載。
- 如果在一個類中有多個相同名字的方法,但參數(shù)不同,則稱為方法重載。
- 父類中有一個方法,子類中有另外一個和它有相同簽名(方法名相同,參數(shù)相同、修飾符相同)的方法時,則稱為方法重寫。子類在重寫父類方法的時候可以加一個 @Override 注解。
19、`main()` 方法可以重載嗎?
可以,一個類中可以有多個名稱為“main”的方法:
- public class MainTest {
- public static void main(String[] args) {
- System.out.println("main(String[] args)");
- }
- public static void main(String[] args,String arg) {
- System.out.println("(String[] args,String arg");
- }
- }
但該類在運行的時候,只會找到一個入口,即 public static void main(String[] args)。
20、一個 Java 源文件中有多個 public 類嗎?
一個 Java 源文件中不能有多個 public 類。
21、什么是 Java 的 package(包)?
在 Java 中,我們使用 package(包)對相關(guān)的類、接口和子包進(jìn)行分組。這樣做的好處有:
- 使相關(guān)類型更容易查找
- 避免命名沖突,比如說 com.itwanger.Hello 和 com.itwangsan.Hello 不同
- 通過包和訪問權(quán)限控制符來限定類的可見性
可以使用 package 關(guān)鍵字來定義一個包名,需要注意的是,這行代碼必須處于一個類中的第一行。強烈建議在包中聲明類,不要缺省,否則就失去了包結(jié)構(gòu)的帶來的好處。
包的命名應(yīng)該遵守以下規(guī)則:
- 應(yīng)該全部是小寫字母
- 可以包含多個單詞,單詞之間使用“.”連接,比如說 java.lang
- 名稱由公司名或者組織名確定,采用倒序的方式,比如說,我個人博客的域名是 www.itwanger.com,所以我創(chuàng)建的包名是就是 com.itwanger.xxxx。
每個包或者子包都在磁盤上有自己的目錄結(jié)構(gòu),如果 Java 文件時在 com.itwanger.xxxx 包下,那么該文件所在的目錄結(jié)構(gòu)就應(yīng)該是 com->itwanger->xxxx。
默認(rèn)情況下,java.lang 包是默認(rèn)導(dǎo)入的,我們不需要顯式地導(dǎo)入該包下的任何類。
- package com.cmower.bb;
- public class PackageTest {
- public static void main(String[] args) {
- Boolean.toString(true);
- }
- }
Boolean 類屬于 java.lang 包,當(dāng)使用它的時候并不需要顯式導(dǎo)入。
22、什么是訪問權(quán)限修飾符?
訪問權(quán)限修飾符對于 Java 來說,非常重要,目前共有四種:public、private、protected 和 default(缺?。?。
一個類只能使用 public 或者 default 修飾,public 修飾的類你之前已經(jīng)見到過了,現(xiàn)在我來定義一個缺省權(quán)限修飾符的類給你欣賞一下。
- class Dog {
- }
哈哈,其實也沒啥可以欣賞的。缺省意味著這個類可以被同一個包下的其他類進(jìn)行訪問;而 public 意味著這個類可以被所有包下的類進(jìn)行訪問。
假如硬要通過 private 和 protected 來修飾類的話,編譯器會生氣的,它不同意。
private 可以用來修飾類的構(gòu)造方法、字段和方法,只能被當(dāng)前類進(jìn)行訪問。protected 也可以用來修飾類的構(gòu)造方法、字段和方法,但它的權(quán)限范圍更寬一些,可以被同一個包中的類進(jìn)行訪問,或者當(dāng)前類的子類。
可以通過下面這張圖來對比一下四個權(quán)限修飾符之間的差別:
- 同一個類中,不管是哪種權(quán)限修飾符,都可以訪問;
- 同一個包下,private 修飾的無法訪問;
- 子類可以訪問 public 和 protected 修飾的;
- public 修飾符面向世界,哈哈,可以被所有的地方訪問到。
23、什么是 final 關(guān)鍵字?
final 關(guān)鍵字修飾類的時候,表示該類無法被繼承。比如,String 類就是 final 的,無法被繼承。
final 關(guān)鍵字修飾方法的時候,表示子類無法覆蓋它。
final 關(guān)鍵字修飾變量的時候,表示該變量只能被賦值一次,盡管變量的狀態(tài)可以更改。
關(guān)于 final 更詳細(xì)的內(nèi)容,可以參照我之前寫了另外一篇文章:
我去,你竟然還不會用 final 關(guān)鍵字
24、什么是 static 關(guān)鍵字?
static 關(guān)鍵字可以用來修飾類變量,使其具有全局性,即所有對象將共享同一個變量。
static 關(guān)鍵字可以用來修飾方法,該方法稱為靜態(tài)方法,只可以訪問類的靜態(tài)變量,并且只能調(diào)用類的靜態(tài)方法。
關(guān)于 static 更詳細(xì)的內(nèi)容,可以參照我之前寫了另外一篇文章:
面試官:兄弟,說說Java的static關(guān)鍵字吧
25、finally 和 finalize 有什么區(qū)別?
finally 通常與 try-catch 塊一起使用,即使 try-catch 塊引發(fā)了異常,finally 塊中的代碼也會被執(zhí)行,用于釋放 try 塊中創(chuàng)建的資源。
finalize() 是 Object 類的一個特殊方法,當(dāng)對象正在被垃圾回收時,垃圾收集器將會調(diào)用該方法??梢灾貙懺摲椒ㄓ糜卺尫畔到y(tǒng)資源。
26、可以將一個類聲明為 static 的嗎?
不能將一個外部類聲明為 static 的,但可以將一個內(nèi)部類聲明為 static 的——稱為靜態(tài)內(nèi)部類。
27、什么是靜態(tài)導(dǎo)入?
如果必須在一個類中使用其他類的靜態(tài)變量或者靜態(tài)方法,通常我們需要先導(dǎo)入該類,然后使用“類名.變量/方法”的形式調(diào)用。
- import java.lang.Math;
- double test = Math.PI * 5;
也可以通過靜態(tài)導(dǎo)入的方式,就不需要再使用類名了。
- import static java.lang.Math.PI;
- double test = PI * 5;
不過,靜態(tài)導(dǎo)入容易引發(fā)混亂(變量名或者方法名容易沖突),因此最好避免使用靜態(tài)導(dǎo)入。
28、什么是 try-with-resources?
try-with-resources 是 Java 7 時引入的一個自動資源管理語句,在此之前,我們必須通過 try-catch-finally 的方式手動關(guān)閉資源,當(dāng)我們忘記關(guān)閉資源的時候,就容易導(dǎo)致內(nèi)存泄漏。
關(guān)于 try-with-resources 更詳細(xì)的內(nèi)容,可以參照我之前寫了另外一篇文章:
我去,你竟然還在用 try–catch-finally
29、什么是 multi-catch?
Java 7 改進(jìn)的另外一個地方就是 multi-catch,可以在單個 catch 中捕獲多個異常,當(dāng)一個 try 塊拋出多個類似的異常時,這種寫法更短,更清晰。
- catch(IOException | SQLException ex){
- logger.error(ex);
- throw new MyException(ex.getMessage());
- }
當(dāng)有多個異常的時候,可以使用管道表示符“|”隔開。
30、什么是 static 塊?
static 塊是由 Java ClassLoader 將類加載到內(nèi)存中時執(zhí)行的代碼塊。通常用于初始化類的靜態(tài)變量或者創(chuàng)建靜態(tài)資源。
31、什么是接口?
接口是 Java 編程語言中的一個核心概念,不僅在 JDK 源碼中使用很多,還在 Java 設(shè)計模式、框架和工具中使用很多。接口提供了一種在 Java 中實現(xiàn)抽象的方法,用于定義子類的行為約定。
關(guān)于接口更詳細(xì)的內(nèi)容,可以參照我之前寫了另外一篇文章:
可能是把 Java 接口講得最通俗的一篇文章
鳴謝
說句實在話,這 31 道 Java 核心面試題在面試的過程中還是很常見的,值得好好復(fù)習(xí)一遍。