1. 程式人生 > >2018年最新JAVA面試題總結之基礎(1)

2018年最新JAVA面試題總結之基礎(1)

轉自於:https://zhuanlan.zhihu.com/p/39322967

 

1、JAVA中能建立volatile陣列嗎?volatile能使得一個非原子操作變成原子操作嗎?


回答: 能,Java 中可以建立 volatile 型別陣列,不過只是一個指向陣列的引用,而不是整個陣列。
Java 中讀取 long 型別變數不是原子的,需要分成兩步,如果一個執行緒正在修改該 long 變數的值,另一個執行緒可能只能看到該值的一半(前 32 位)。但是volatile 型的 long 或 double 變數的讀寫是原子。

2、10個執行緒和2個執行緒的同步程式碼,哪個更容易寫?
回答:從寫程式碼的角度來說,兩者的複雜度是相同的,因為同步程式碼與執行緒數量是相互獨立的。但是同步策略的選擇依賴於執行緒的數量,因為越多的執行緒意味著更大的競爭,所以你需要利用同步技術,如鎖分離,這要求更復雜的程式碼和專業知識。
3、什麼是執行緒區域性變數?
回答: 對於多執行緒資源共享的問題,同步機制採用了“以時間換空間”的方式,而ThreadLocal採用了“以空間換時間”的方式。前者僅提供一份變數,讓不同的執行緒排隊訪問,而後者為每一個執行緒都提供了一份變數,因此可以同時訪問而互不影響。

4、我們自己寫一個容器類,然後使用for-each迴圈嗎?
回答:可以,你可以寫一個自己的容器類。如果你想使用 Java 中增強的迴圈來遍歷,你只需要實現 Iterable介面。如果你實現 Collection 介面,預設就具有該屬性。


5、說出5條IO的最佳實踐?
回答:1.使用有緩衝區的 IO 類,而不要單獨讀取位元組或字元。
2.使用 NIO 和 NIO2
3.在 finally 塊中關閉流,或者使用 try-with-resource 語句。
4.使用記憶體對映檔案獲取更快的 IO。
5.使用非阻塞式而不要使用阻塞式的IO

6、說出至少5點在Java中使用執行緒的最佳實踐?
回答:1.對執行緒命名

2.將執行緒和任務分離,使用執行緒池執行器來執行 Runnable 或 Callable。

3.使用執行緒池

4.如果可以,更偏向於使用 volatile 而不是 synchronized。

5.優先使用併發集合,而不是對集合進行同步。併發集合提供更好的可擴充套件性。

7、我能在不進行強制轉換的情況下將一個double值賦值給long型別的變數嗎?
回答:不行,因為 double 型別的範圍比 long 型別更廣,所以必須要進行強制轉換。

8、我們能在Switch中使用String嗎?
回答:在jdk 7 之前,switch 只能支援 byte、short、char、int 這幾個基本資料型別和其對應的封裝型別。switch後面的括號裡面只能放int型別的值,但由於byte,short,char型別,它們會 自動 轉換為int型別(精精度小的向大的轉化),所以它們也支援。
jdk1.7後,整形,列舉型別,boolean,字串都可以。
jdk1.7並沒有新的指令來處理switch string,而是通過呼叫switch中string.hashCode,將string轉換為int從而進行判斷。

9、poll()方法和remove()方法的區別?
回答: poll() 和 remove() 都是從佇列中取出一個元素,但是 poll() 在獲取元素失敗的時候會返回空,但是 remove() 失敗的時候會丟擲異常。

10、LinkedList和ArrayList的區別?
回答:1.ArrayList和LinkedList可想從名字分析,它們一個是Array(動態陣列)的資料結構,一個是Link(連結串列)的資料結構,此外,它們兩個都是前者是陣列佇列,相當於動態陣列;後者為雙向連結串列結構,也可當作堆疊、佇列、雙端佇列對List介面的實現。

2.當隨機訪問List時(get和set操作),ArrayList比LinkedList的效率更高,因為LinkedList是線性的資料儲存方式,所以需要移動指標從前往後依次查詢。

3.當對資料進行增加和刪除的操作時(add和remove操作),LinkedList比ArrayList的效率更高,因為ArrayList是陣列,所以在其中進行增刪操作時,會對操作點之後所有資料的下標索引造成影響,需要進行資料的移動。

4.從利用效率來看,ArrayList自由性較低,因為它需要手動的設定固定大小的容量,但是它的使用比較方便,只需要建立,然後新增資料,通過呼叫下標進行使用;而LinkedList自由性較高,能夠動態的隨資料量的變化而變化,但是它不便於使用。

5.ArrayList主要控制元件開銷在於需要在lList列表預留一定空間;而LinkList主要控制元件開銷在於需要儲存結點資訊以及結點指標資訊。

11、hashmap的擴容問題new hashmap(19)它的長度是多少?
回答:初始長度是19,當達到預設載入因子的時候會進行擴容
12、hashtable為什麼是執行緒安全的?
回答:Hashtable是執行緒安全的,其實現方式是在對應的方法上加上synchronized關鍵字,效率不高,不建議使用。目前,如果要使用執行緒安全的雜湊表的話,推薦使用ConcurrentHashMap。

13、java異常處理怎麼做?
回答:1.對程式碼塊用try..catch進行異常捕獲處理;

2.在 該程式碼的方法體外用throws進行丟擲宣告,告知此方法的呼叫者這段程式碼可能會出現這些異常,你需要謹慎處理。此時有兩種情況:1)如果宣告丟擲的異常是非執行時異常,此方法的呼叫者必須顯示地用try..catch塊進行捕獲或者繼續向上層丟擲異常;2)如果宣告丟擲的異常是執行時異常,此方法的呼叫者可以選擇地進行異常捕獲處理。

3.在程式碼塊用throw手動丟擲一個異常物件,此時也有兩種情況,跟2中的類似:1)如果丟擲的異常物件是非執行時異常,此方法的呼叫者必須顯示地用try..catch塊進行捕獲或者繼續向上層丟擲異常;2)如果丟擲的異常物件是執行時異常,此方法的呼叫者可以選擇地進行異常捕獲處理。

14、異常處理的作用是什麼?
回答: 因為你不可能保證程式不出錯,所以使用異常處理來防止程式出錯的時候你無從下手的局面,對於除錯程式和專案實際開發都是有用的

15、jvm記憶體的分配?
回答:1.程式計數器:執行緒私有,當前執行緒執行的位元組碼的行號指示器。

2.虛擬機器棧:執行緒私有,存放基本資料型別、物件引用和returnAddress型別。
3.本地方法棧:為虛擬機器使用到的Native方法服務。
4.Java堆:執行緒共享,存放物件的例項,也是GC回收器管理的主要區域。
5.方法區:執行緒共享,存放已被虛擬機器載入的類資訊、常量、靜態變數、即時編譯後的程式碼等資料。 
6.執行時常量池:方法區的一部分,存放編譯期生成的各種字面量和符號引用。
7.直接記憶體:不是虛擬機器執行時資料區的一部分,也不是Java虛擬機器規範中定義的記憶體區域,容易引起OOM異常,NIO會呼叫,不受Java堆大小的限制。

16、Abstract和interface區別?
回答:1.abstract class 在 Java 語言中表示的是一種繼承關係,一個類只能使用一次繼承關係。但是,一個類卻可以實現多個interface。
2.在abstract class 中可以有自己的資料成員,也可以有非abstarct的成員方法,而在interface中,只能夠有靜態的不能被修改的資料成員(也就是必須是static final的,不過在 interface中一般不定義資料成員),所有的成員方法都是abstract的。
3.abstract class和interface所反映出的設計理念不同。其實abstract class表示的是"is-a"關係,interface表示的是"like-a"關係。
4.實現抽象類和介面的類必須實現其中的所有方法。抽象類中可以有非抽象方法。介面中則不能有實現方法。
5.介面中定義的變數預設是public static final 型,且必須給其初值,所以實現類中不能重新定義,也不能改變其值。
6.抽象類中的變數預設是 friendly 型,其值可以在子類中重新定義,也可以重新賦值。
7.介面中的方法預設都是 public,abstract 型別的。

17、有沒有遇到過記憶體溢位,記憶體溢位怎麼解決?
回答: 分不同情況解決,大多數情況下,此時如果程式碼沒有問題的情況下,適當調整-Xmx和-Xms是可以避免的,不過一定是程式碼沒有問題的前提,為什麼會溢位呢,要麼程式碼有問題,要麼訪問量太多並且每個訪問的時間太長或者資料太多,導致資料釋放不掉,因為垃圾回收器是要找到那些是垃圾才能回收,這裡它不會認為這些東西是垃圾,自然不會去回收了。

18、jvm調優有哪幾種方式
回答:1.觀察記憶體釋放情況、集合類檢查、物件樹
2.執行緒監控
3.記憶體洩漏檢查
4.具體調優方式:



19、java中invokeAndWait和invokeLater有什麼區別?
回答: 這兩個方法是Swing API 提供給Java開發者用來從當前執行緒而不是事件派發執行緒更新GUI元件用的。InvokeAndWait()同步更新GUI元件,比如一個進度條,一旦進度更新了,進度條也要做出相應改變。如果進度被多個執行緒跟蹤,那麼就呼叫invokeAndWait()方法請求事件派發執行緒對元件進行相應更新。而invokeLater()方法是非同步呼叫更新元件的。

20、Swing API中哪些方法是執行緒安全的?
回答:Swing的規則是:一旦Swing元件被具現化(realized),所有可能影響或依賴於元件狀態的程式碼都應該在事件派發執行緒中執行。所以有這3個執行緒安全的方法:repaint(),revalidate(),andinvalidate()。

21、如何在Java中建立immutable物件?
回答: 1.immutable物件的狀態在建立之後就不能發生改變,任何對它的改變都應該產生一個新的物件。
2.Immutable類的所有的屬性都應該是final的。
3.物件必須被正確的建立,比如:物件引用在物件建立過程中不能洩露(leak)。
4.物件應該是final的,以此來限制子類繼承父類,以避免子類改變了父類的immutable特性。
5.如果類中包含mutable類物件,那麼返回給客戶端的時候,返回該物件的一個拷貝,而不是該物件本身(該條可以歸為第一條中的一個特例)

22、Java中的readwritelock是什麼?
回答: 一般而言,讀寫鎖是用來提升併發程式效能的鎖分離技術的成果。Java中的ReadWriteLock是Java 5 中新增的一個介面,一個ReadWriteLock維護一對關聯的鎖,一個用於只讀操作一個用於寫。在沒有寫執行緒的情況下一個讀鎖可能會同時被多個讀執行緒 持有。寫鎖是獨佔的,你可以使用JDK中的ReentrantReadWriteLock來實現這個規則,它最多支援65535個寫鎖和65535個讀 鎖。

23、多執行緒中的忙迴圈是什麼?
回答: 忙迴圈就是程式設計師用迴圈讓一個執行緒等待,不像傳統方法wait(), sleep() 或 yield() 它們都放棄了CPU控制,而忙迴圈不會放棄CPU,它就是在執行一個空迴圈。這麼做的目的是為了保留CPU快取,在多核系統中,一個等待執行緒醒來的時候可能會在另一個核心執行,這樣會重建快取。為了避免重建快取和減少等待重建的時間就可以使用它了。 

24、volatile變數和atomic變數有什麼不同?
回答:volatile 變數和 atomic 變數看起來很像,但功能卻不一樣。Volatile變數可以確保先行關係,即寫操作會發生在後續的讀操作之前, 但它並不能保證原子性。例如用volatile修飾count變數那麼 count++ 操作就不是原子性的。而AtomicInteger類提供的atomic方法可以讓這種操作具有原子性如getAndIncrement()方法會原子性的進行增量操作把當前值加一,其它資料型別和引用變數也可以進行相似操作。

25、如果同步塊內的執行緒丟擲異常會發生什麼?
回答: 這個問題坑了很多Java程式設計師,若你能想到鎖是否釋放這條線索來回答還有點希望答對。無論你的同步塊是正常還是異常退出的,裡面的執行緒都會釋放鎖,所以對比鎖介面我更喜歡同步塊,因為它不用我花費精力去釋放鎖,該功能可以在finally block裡釋放鎖實現。 

26、單例模式的雙檢鎖式是什麼?
回答: 雙重檢驗鎖模式(double checked locking pattern),是一種使用同步塊加鎖的方法。程式設計師稱其為雙重檢查鎖,因為會有兩次檢查 instance == null,一次是在同步塊外,一次是在同步塊內。為什麼在同步塊內還要再檢驗一次?因為可能會有多個執行緒一起進入同步塊外的 if,如果在同步塊內不進行二次檢驗的話就會生成多個例項了。

27、如何在Java中建立執行緒安全的singleton?
回答:
public class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static synchronized Singleton getInstance(){
if (instance == null) instance = new Singleton();
return instance;
}
}


28、說說jdk1.8的新特性?
回答:1.隨著大資料的興起,函數語言程式設計在處理大資料上的優勢開始體現,引入了Lambada函數語言程式設計
2.使用Stream徹底改變了集合使用方式:只關注結果,不關心過程
3.新的客戶端圖形化工具介面庫:JavaFX
4.良好設計的日期/時間API
5.增強的併發/並行API
6.Java與JS互動引擎 -nashorn
7.其他特性

29、gc回收機制原理?
回答:使用者Java程式執行過程中,Java虛擬機器提供了另外一個系統級的執行緒,專門負責回收不再被使用的物件佔用的記憶體,這一過程稱為垃圾回收。垃圾回收需要對堆記憶體中的物件進行標記,並對堆記憶體進行整理。這一過程的某些階段需要暫時終止使用者Java執行緒,等回收工作完成後再恢復執行。因此,頻繁地觸發虛擬機器垃圾回收操作的行為會影響程式的執行效率。那麼什麼情況下會頻繁地出發垃圾回收操作呢?- 比如:堆記憶體設定過小- 再比如:程式頻繁地分配大型區域性物件陣列。