JDK基礎必備面試十問
1. new一個物件在Java內部做了哪些工作?
從靜態角度來看,new一個物件表示建立一個類的物件例項。
從JVM執行角度來看,當JVM執行到new位元組碼時,首先會去檢視類有沒有被載入到記憶體以及初始化,如果是第一次使用該類,則首先載入該類。載入完成後便會在堆記憶體分配該物件例項的記憶體空間,虛擬機器棧分配物件例項的應用記憶體。
2. 抽象類是否可以定義建構函式?如果能,是否能new一個抽象類?
抽象類同樣也可以定義建構函式,但是它不能new一個抽象類。
3. 既然不能new一個抽象類,那它定義建構函式有什麼意義呢?
抽象類中的建構函式只能通過建構函式鏈呼叫,也就是從其他類中的建構函式呼叫,它的作用可以初始化抽象類中的一些初始值。
4. String是否是基本資料型別?它與StringBuilder、StringBuffer有什麼區別?
String不是基本資料型別。
String是不可變的,儘管它能在程式中多次賦值以及拼接,但實際上每一次賦值都是在記憶體中重新開闢一塊記憶體空間。
StringBuilder和StringBuffer是可變的,多次對它們賦值不會在記憶體中開闢一塊記憶體空間,StringBuilder不是執行緒安全,StringBuffer是執行緒安全的。
5. StringBuilder與StringBuffer的內部實現原理是什麼?
StringBuffer與StringBuilder的不同點在於StringBuffer在append方法加了synchronized關鍵字,它是執行緒安全的。
它們都是繼承自AbstractBuilder,內部實現都是一個可變陣列,陣列初始長度為16。當呼叫append方法拼接字串時,其內部實際上是呼叫了System.arraycopy將字串拷貝進了可變陣列。
6. StringBuilder的擴容機制是什麼?
StringBuilder在內部是一個字元陣列,預設大小為16,當容量超過16時,會進行擴容,新的陣列大小是之前陣列大小的2倍+2,也就是第一次擴容大小為34。擴容後將以前的陣列拷貝到新陣列中。
7. String str = "a"與String str = new String("b")有什麼區別?
String str = "a",首先會去常量池中查詢是否有"a"字串,如果有則直接指向它,沒有則在常量池中建立並指向它。
String str = new String("b")則會在堆記憶體中建立一個String物件例項,並指向它,同時它也會在常量池中建立"b"物件。
8. ==與equals比較有什麼區別?
==比較的是引用地址,
equals通常比較的是值,equals在Object中的實現仍然是==,所以如果要通過equals比較值就必須重寫equals。
9. 重寫equals方法需要注意什麼?
在重寫equals方法時,一定要重寫hashCode方法,hashCode方法是計算物件的hash值。
在Java中規定:
equals等於true,則它們的hashCode一定相等;
equals等於false,則它們的hashCode可能相等可能不相等,也就是如果hashCode相等,則equals不一定相等。
之所以要重寫hashCode方法,主要是應用在集合中的判斷。
如果沒有重寫類的hashCode方法,只重寫了equals方法,當兩個物件equals等於true時,它們的hashCode不相等。此時如果將它們作為key放到Map集合中,由於它們的hash值不相等,所以Map認為它們是不相等的key,此時在Map中將會在邏輯上存在兩個相等的key值,不符合我們對程式的預期。所以在重寫equals方法時必須重寫hashCode方法。
10. 重寫hashCode方法需要注意什麼?
在設計雜湊函式時,應該儘量避免衝突。如果頻繁的產生雜湊衝突,在將物件作為key存放在Map中時,會將不同的key值雜湊到一個位置,對Map的效能會有所影響。可以參考String的hashCode實現,將質數31數字作為乘法因子。
關注CoderBuff公眾號,回覆“面試”獲取更多