Java面試之高級特性基礎(chǔ)總結(jié)
1.為什么 Java 中只有值傳遞
- 值傳遞 :方法接收的是實參值的拷貝,會創(chuàng)建副本。
- 引用傳遞 :方法接收的直接是實參所引用的對象在堆中的地址,不會創(chuàng)建副本,對形參的修改將影響到實參。
很多程序設(shè)計語言(比如 C++、 Pascal )提供了兩種參數(shù)傳遞的方式,不過,在 Java 中只有值傳遞。
Java 中將實參傳遞給方法(或函數(shù))的方式是 值傳遞 :
- 如果參數(shù)是基本類型的話,很簡單,傳遞的就是基本類型的字面量值的拷貝,會創(chuàng)建副本。
- 如果參數(shù)是引用類型,傳遞的就是實參所引用的對象在堆中地址值的拷貝,同樣也會創(chuàng)建副本。
2.static 關(guān)鍵字使用場景
修飾成員變量和成員方法:
被 static 修飾的成員屬于類,不屬于單個這個類的某個對象,被類中所有對象共享,可以并且建議通過類名調(diào)用。被 static 聲明的成員變量屬于靜態(tài)成員變量,靜態(tài)變量 存放在 Java 內(nèi)存區(qū)域的方法區(qū)。
靜態(tài)代碼塊:
靜態(tài)代碼塊定義在類中方法外, 靜態(tài)代碼塊在非靜態(tài)代碼塊之前執(zhí)行(靜態(tài)代碼塊 —> 非靜態(tài)代碼塊 —> 構(gòu)造方法)。 該類不管創(chuàng)建多少對象,靜態(tài)代碼塊只執(zhí)行一次
靜態(tài)導(dǎo)包:
格式為:import static
這兩個關(guān)鍵字連用可以指定導(dǎo)入某個類中的指定靜態(tài)資源,并且不需要使用類名調(diào)用類中靜態(tài)成員,可以直接使用類中靜態(tài)成員變量和成員方法
import static java.lang.Math.*;
public class Demo {
public static void main(String[] args) {
int max = max(1,2);
System.out.println(max);
}
}
靜態(tài)內(nèi)部類:
靜態(tài)內(nèi)部類與非靜態(tài)內(nèi)部類之間存在一個最大的區(qū)別,我們知道非靜態(tài)內(nèi)部類在編譯完成之后會隱含地保存著一個引用,該引用是指向創(chuàng)建它的外圍類,但是靜態(tài)內(nèi)部類卻沒有。沒有這個引用就意味著:
1.它的創(chuàng)建是不需要依賴外圍類的創(chuàng)建。
2.它不能使用任何外圍類的非 static 成員變量和方法。
例如:靜態(tài)內(nèi)部類實現(xiàn)單例模式:
public class Singleton {
// 聲明為 private 避免調(diào)用默認構(gòu)造方法創(chuàng)建對象
private Singleton() {
}
// 聲明為 private 表明靜態(tài)內(nèi)部該類只能在該 Singleton 類中被訪問
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getUniqueInstance() {
return SingletonHolder.INSTANCE;
}
}
當 Singleton 類加載時,靜態(tài)內(nèi)部類 SingletonHolder 沒有被加載進內(nèi)存。只有當調(diào)用 getUniqueInstance()方法從而觸發(fā) SingletonHolder.INSTANCE 時 SingletonHolder 才會被加載,此時初始化 INSTANCE 實例,并且 JVM 能確保 INSTANCE 只被實例化一次。
這種方式不僅具有延遲初始化的好處,而且由 JVM 提供了對線程安全的支持。
3.Exception 和 Error 有什么區(qū)別
在 Java 中,所有的異常都有一個共同的祖先 java.lang 包中的 Throwable 類。Throwable 類有兩個重要的子類:
- Exception :程序本身可以處理的異常,可以通過 catch 來進行捕獲。Exception 又可以分為 Checked Exception (受檢查異常,必須處理) 和 Unchecked Exception (不受檢查異常,可以不處理)。
- Error :Error 屬于程序無法處理的錯誤 ,不建議通過catch捕獲 。例如 Java 虛擬機運行錯誤(Virtual MachineError)、虛擬機內(nèi)存不夠錯誤(OutOfMemoryError)、類定義錯誤(NoClassDefFoundError)等 。這些異常發(fā)生時,Java 虛擬機(JVM)一般會選擇線程終止。
4.Checked Exception 和 Unchecked Exception 有什么區(qū)別
Checked Exception 即 受檢查異常 ,Java 代碼在編譯過程中,如果受檢查異常沒有被 catch或者throws 關(guān)鍵字處理的話,就沒辦法通過編譯。
比如下面這段 IO 操作的代碼:

除了RuntimeException及其子類以外,其他的Exception類及其子類都屬于受檢查異常 。常見的受檢查異常有: IO相關(guān)的異常、ClassNotFoundException 、SQLException…
Unchecked Exception 即 不受檢查異常 ,Java 代碼在編譯過程中 ,我們即使不處理不受檢查異常也可以正常通過編譯。
RuntimeException 及其子類都統(tǒng)稱為非受檢查異常
常見的Unchecked Exception:
- NullPointerException(空指針錯誤)
- IllegalArgumentException(參數(shù)錯誤比如方法入?yún)㈩愋湾e誤)
- NumberFormatException(字符串轉(zhuǎn)換為數(shù)字格式錯誤,IllegalArgumentException的子類)
- ArrayIndexOutOfBoundsException(數(shù)組越界錯誤)
- ClassCastException(類型轉(zhuǎn)換錯誤)
- ArithmeticException(算術(shù)錯誤)
- SecurityException (安全錯誤比如權(quán)限不夠)
- UnsupportedOperationException(不支持的操作錯誤比如重復(fù)創(chuàng)建同一用戶)
5.Throwable 類常用方法有哪些
String getMessage(): 返回異常發(fā)生時的簡要描述
String toString(): 返回異常發(fā)生時的詳細信息
String getLocalizedMessage(): 返回異常對象的本地化信息。使用 Throwable 的子類覆蓋這個方法,可以生成本地化信息。如果子類沒有覆蓋該方法,則該方法返回的信息與 getMessage()返回的結(jié)果相同
void printStackTrace(): 在控制臺上打印 Throwable 對象封裝的異常信息
6.finally 中的代碼一定會執(zhí)行嗎
在某些情況下,finally 中的代碼不會被執(zhí)行。
就比如說 finally 之前虛擬機被終止運行的話,finally 中的代碼就不會被執(zhí)行。
public static void main(String[] args) {
try {
System.out.println("Do something");
throw new RuntimeException("RuntimeException");
} catch (Exception e) {
System.out.println(e.getMessage());
// 終止當前正在運行的Java虛擬機
System.exit(1);
} finally {
System.out.println("Finally");
}
}
這個程序只會輸出:
Do something
RuntimeException
另外,在以下 2 種特殊情況下,finally 塊的代碼也不會被執(zhí)行:
- 程序所在的線程死亡
- 關(guān)閉 CPU
7.如何使用 try-with-resources 代替try-catch-finally
面對必須要關(guān)閉的資源,我們總是應(yīng)該優(yōu)先使用 try-with-resources 而不是try-finally。try-with-resources語句讓我們更容易編寫必須要關(guān)閉的資源的代碼,若采用try-finally則幾乎做不到這點。
Java 中類似于InputStream、OutputStream 、Scanner 、PrintWriter等的資源都需要我們調(diào)用close()方法來手動關(guān)閉,一般情況下我們都是通過try-catch-finally語句來實現(xiàn)這個需求,如下:
public static void main(String[] args) {
// 讀取文本文件的內(nèi)容
Scanner scanner = null;
try {
scanner = new Scanner(new File("D://read.txt"));
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
if (scanner != null) {
scanner.close();
}
}
}使用 Java 7 之后的 try-with-resources 語句改造上面的代碼:
public static void main(String[] args) {
try (Scanner scanner = new Scanner(new File("D://read.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
}
當然多個資源需要關(guān)閉的時候,使用 try-with-resources 實現(xiàn)起來也非常簡單:
通過使用分號分隔,可以在try-with-resources塊中聲明多個資源:
try (BufferedInputStream bin = new BufferedInputStream(new FileInputStream(new File("test.txt")));
BufferedOutputStream bout = new BufferedOutputStream(new FileOutputStream(new File("out.txt")))) {
int b;
while ((b = bin.read()) != -1) {
bout.write(b);
}
}
catch (IOException e) {
e.printStackTrace();
}
8.注解的解析方法有哪幾種
注解只有被解析之后才會生效,常見的解析方法有兩種:
- 編譯期直接掃描 :編譯器在編譯 Java 代碼的時候掃描對應(yīng)的注解并處理,比如某個方法使用@Override 注解,編譯器在編譯的時候就會檢測當前的方法是否重寫了父類對應(yīng)的方法。
- 運行期通過反射處理 :像框架中自帶的注解(比如 Spring 框架的 @Value 、@Component)都是通過反射來進行處理的。
9.泛型的使用方式有哪幾種
泛型一般有三種使用方式:泛型類、泛型接口、泛型方法
10.項目中哪里用到了泛型
1.自定義接口通用返回結(jié)果 CommonResult<T> 通過參數(shù) T 可根據(jù)具體的返回類型動態(tài)指定結(jié)果的數(shù)據(jù)類型
2.定義 Excel 處理類 ExcelUtil<T> 用于動態(tài)指定 Excel 導(dǎo)出的數(shù)據(jù)類型
3.構(gòu)建集合工具類(參考 Collections 中的 sort, binarySearch 方法)。
到此這篇關(guān)于Java面試之高級特性基礎(chǔ)總結(jié)的文章就介紹到這了,更多相關(guān)Java高級特性內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

