繼上篇JVM學習以後,後面將分三期深刻介紹剩餘JAVA基礎面試題,每期3題。html
題目1、final,finally,finalize有什麼區別?java
/*請尊重做者勞動成果,轉載請標明原文連接:*/面試
/* https://www.cnblogs.com/jpcflyer/p/10739217.html* /編程
你們通常都這麼回答:
final 能夠用來修飾類、方法、變量,分別有不一樣的意義,final 修飾的 class 表明不能夠繼承擴展,final 的變量是不能夠修改的,而 final 的方法也是不能夠重寫的(override)。
finally 則是 Java 保證重點代碼必定要被執行的一種機制。咱們可使用 try-finally 或者 try-catch-finally 來進行相似關閉 JDBC 鏈接、保證 unlock 鎖等動做。
finalize 是基礎類 java.lang.Object 的一個方法,它的設計目的是保證對象在被垃圾收集前完成特定資源的回收。finalize 機制如今已經不推薦使用,而且在 JDK 9 開始被標記爲 deprecated。
從語法層次,這樣說完是沒有問題的,但讓咱們深刻一下,何時會用到final?
若是你關注過 Java 核心類庫的定義或源碼, 有沒有發現 java.lang 包下面的不少類,至關一部分都被聲明成爲 final class?在第三方類庫的一些基礎類中一樣如此,這能夠有效避免 API 使用者更改基礎功能,某種程度上,這是保證平臺安全的必要手段。
使用 final 修飾參數或者變量,也能夠清楚地避免意外賦值致使的編程錯誤,甚至,有人明確推薦將全部方法參數、本地變量、成員變量聲明成 final。
final 變量產生了某種程度的不可變(immutable)的效果,因此,能夠用於保護只讀數據,尤爲是在併發編程中,由於明確地不能再賦值 final 變量,有利於減小額外的同步開銷,也能夠省去一些防護性拷貝的必要。
另外,有一些常被考到的 finally 問題(也比較偏門),至少須要瞭解一下。好比,下面代碼會輸出什麼?
1 try { 2 // do something
3 System.exit(1); 4 } finally{ 5 System.out.println(「Print from finally」); 6 }
上面 finally 裏面的代碼可不會被執行的哦,這是一個特例。數組
若是須要關閉鏈接等資源,推薦使用 Java 7 中添加的 try-with-resources 語句,由於一般 Java 平臺可以更好地處理異常狀況,編碼量也要少不少,何樂而不爲呢。
對於 finalize,咱們要明確它是不推薦使用的,業界實踐一再證實它不是個好的辦法,在 Java 9 中,甚至明確將 Object.finalize() 標記爲 deprecated!若是沒有特別的緣由,不要實現 finalize 方法,也不要期望利用它來進行資源回收。
爲何呢?簡單說,你沒法保證 finalize 何時執行,執行的是否符合預期。使用不當會影響性能,致使程序死鎖、掛起等。
題目2、String, StringBuffer, StringBuilder有什麼區別?
接下來聊一聊平常使用的字符串,別看它彷佛簡單,但實際上字符串涉及到的知識點特別多,在編程的大部分時候也都是在和字符串打交道。
通常回答:
String 是 Java 語言很是基礎和重要的類,提供了構造和管理字符串的各類基本邏輯。它是典型的 Immutable 類,被聲明成爲 final class,全部屬性也都是 final 的。也因爲它的不可變性,相似拼接、裁剪字符串等動做,都會產生新的 String 對象。因爲字符串操做的廣泛性,因此相關操做的效率每每對應用性能有明顯影響。
StringBuffer 是爲解決上面提到拼接產生太多中間對象的問題而提供的一個類,咱們能夠用 append 或者 add 方法,把字符串添加到已有序列的末尾或者指定位置。StringBuffer 本質是一個線程安全的可修改字符序列,它保證了線程安全,也隨之帶來了額外的性能開銷,因此除非有線程安全的須要,否則仍是推薦使用它的後繼者,也就是 StringBuilder。
StringBuilder 是 Java 1.5 中新增的,在能力上和 StringBuffer 沒有本質區別,可是它去掉了線程安全的部分,有效減少了開銷,是絕大部分狀況下進行字符串拼接的首選。
再繼續擴展一下:
首先看看 StringBuffer 實現的一些細節,它的 線程安全是經過把各類修改數據的方法都加上 synchronized 關鍵字實現的,很是直白。
爲了實現修改字符序列的目的,StringBuffer 和 StringBuilder 底層都是利用可修改的(char,JDK 9 之後是 byte)數組,兩者都繼承了 AbstractStringBuilder,裏面包含了基本操做,區別僅在於最終的方法是否加了 synchronized。
另外,這個內部數組應該建立成多大的呢?若是過小,拼接的時候可能要從新建立足夠大的數組;若是太大,又會浪費空間。目前的實現是,構建時初始字符串長度加 16(這意味着,若是沒有構建對象時輸入最初的字符串,那麼初始值就是 16)。咱們若是肯定拼接會發生很是屢次,並且大概是可預計的,那麼就能夠指定合適的大小,避免不少次擴容的開銷。擴容會產生多重開銷,由於要拋棄原有數組,建立新的(能夠簡單認爲是倍數)數組,還要進行 arraycopy。
題目3、Exception和Error有什麼區別?安全
直接看JAVA異常結構吧,JAVA異常的繼承結構:Throwable爲基類,Error和Exception繼承Throwable,RuntimeException和IOException等繼承Exception。Error和RuntimeException及其子類成爲未檢查異常(unchecked),其它異常成爲已檢查異常(checked)。
Error異常
Error表示程序在運行期間出現了十分嚴重、不可恢復的錯誤,在這種狀況下應用程序只能停止運行,例如JAVA 虛擬機出現錯誤。Error是一種unchecked Exception,編譯器不會檢查Error是否被處理,在程序中不用捕獲Error類型的異常。通常狀況下,在程序中也不該該拋出Error類型的異常。
RuntimeException異常
Exception異常包括RuntimeException異常和其餘非RuntimeException的異常。
RuntimeException 是一種Unchecked Exception,即表示編譯器不會檢查程序是否對RuntimeException做了處理,在程序中沒必要捕獲RuntimException類型的異常,也沒必要在方法體聲明拋出RuntimeException類。RuntimeException發生的時候,表示程序中出現了編程錯誤,因此應該找出錯誤修改程序,而不是去捕獲RuntimeException。
Checked Exception異常
Checked Exception異常,這也是在編程中使用最多的Exception,全部繼承自Exception而且不是RuntimeException的異常都是checked Exception,上圖中的IOException和ClassNotFoundException。JAVA 語言規定必須對checked Exception做處理,編譯器會對此做檢查,要麼在方法體中聲明拋出checked Exception,要麼使用catch語句捕獲checked Exception進行處理,否則不能經過編譯。