20 Essential Java Interview Questions
-
為什么要在避免在抽象類的構造方法中調用其抽象方法?
- 主要是因為初始化順序導致的,因為在父類初始化的時候,子類還沒來得及初始化
利用 類似List<e extents Object> , 而不是 List<Object> 來容納子類
transit 關鍵字的用法?
利用transit 修飾field 可以防止 一些不想被序列化的屬性被序列化
TreeSet 和HashSet 的比較
HashSet 在 add ,remove ,contain 操作都是 O(1) , 而TreeSet 是 O(Log N),可以說HashSet 幾乎在各個方面都是優于TreeSet, 但是TreeSet 是基于Tree 的數據結構來實現的,所以說,TreeSetr 可以保持數據的元素順序。這個特性是HashSet所沒有的
**好萊塢原則 : ** 以通知代替輪訓是好萊塢的核心!
-
為何 String.length() 給出的結果并非準確的?
- 因為String.length() 返回的是char[] 數組的長度,在Java 最初設計時,由于char是一個 16位的變量所它只能覆蓋 Unicode 的第0號平面,如果字符不包含在第0號平面的,將會覆蓋兩個char 字節 具體參考 Uncode 字符衍射
**什么是JIT ? **:深入淺出 JIT 編譯器
JIT 是JVM 在運行時優化代碼的一種機制
高運行頻率的字節碼直接被翻譯為機器指令以提高性能。在JIT將這部分翻譯為機器碼時,是method為單位的。并且翻譯后的機器碼會被保存起來,這樣,在第一次以后調用時,就不需要再進行翻譯
JIT 有兩種模式:server 模式啟動慢,但是運行快,client 模式啟動快,運行慢
JIT 的代碼緩存是有限的,可以利用 命令
–XX:ReservedCodeCacheSize=Nflag
來最大化代碼緩存編譯是基于兩個計數器的:一個是方法被調用的次數,另一個是方法中循環被回彈執行的次數。通過改變
-XX:CompileThreshold=Nflag
的值,可以更改 方法被編譯的閾值,如果在應用的性能瓶頸期,更改這個閾值會帶來一定的性能提升說出下面代碼帶來的便捷
try (final Stream<String> stream = Files.lines(path)){
stream.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
- 利用Paths 攻破那個劇了
- 利用method reference 來簡化控制輸出到控制臺
- Stream 是繼承于AutoCloseable 接口,然后利用 Java 1.7 開始的try - resource 語法,實現了stream的自動關閉,不需要再去寫 try-catch-finally了
- 解釋下面的現象
final List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.remove(2)
最后輸出了 [1,2] , 因為 JVM 總是選擇最為準確的override 方法,remove 兩個重載,remove(int index ) 和 remove(Object object ) 明顯第一個更加準確,雖然Java 有自動裝載功能,但其實在這里沒有用
- 解釋下下面代碼存在的問題
public class Foo {
public Foo() {
doSomething();
}
public void doSomething() {
System.out.println("do something acceptable");
}
}
public class Bar extends Foo {
public void doSomething() {
System.out.println("yolo");
Zoom zoom = new Zoom(this);
}
}
- Bar這個對象在創建時,首先是調用的父類 Foo的 construor 方法,而父類的constructor 方法又調用了子類重寫的 doSomething 方法,這樣在Zoom 引用Bar 對象進行創建的時候,是引用的一個沒有完全初始化完成的對象!!!