1. 程式人生 > >【JAVA秒會技術之秒殺面試官】JavaSE常見面試題(三)

【JAVA秒會技術之秒殺面試官】JavaSE常見面試題(三)

mark error 對象創建 事件 算法 pool ret sync 數量

41..比較一下Java和JavaSciprt?

答:其實Java和JavaScript最重要的區別是一個是靜態語言,一個是動態語言:

(1)基於對象和面向對象:Java是一種真正的面向對象的語言,即使是開發簡單的程序,必須設計對象;JavaScript是種腳本語言,它可以用來制作與網絡無關的,與用戶交互作用的復雜軟件。它是一種基於對象(Object-Based)和事件驅動(Event-Driven)的編程語言,因而它本身提供了非常豐富的內部對象供設計人員使用。

(2)解釋和編譯:Java的源代碼在執行之前,必須經過編譯。JavaScript是一種解釋性編程語言,其源代碼不需經過編譯,由瀏覽器解釋執行。(目前的瀏覽器幾乎都使用了JIT(即時編譯)技術來提升JavaScript的運行效率)

(3)強類型變量和類型弱變量:Java采用強類型變量檢查,即所有變量在編譯之前必須作聲明;JavaScript中變量是弱類型的,甚至在使用變量前可以不作聲明,JavaScript的解釋器在運行時檢查推斷其數據類型。

(4)代碼格式不一樣。

42.Error和Exception有什麽區別?

答:①Error表示系統級的錯誤和程序不必處理的異常,是恢復不是不可能但很困難的情況下的一種嚴重問題;比如內存溢出,不可能指望程序能處理這樣的情況;

②Exception表示需要捕捉或者需要程序進行處理的異常,是一種設計或實現問題;也就是說,它表示如果程序運行正常,從不會發生的情況。

43.try{}裏有一個return語句,那麽緊跟在這個try後的finally{}裏的代碼會不會被執行,什麽時候被執行,在return前還是後?

答:會執行,在方法返回調用者前執行。

44.throw和throws的區別、及處理方式?

答:(1)throw:用於拋出異常對象,後面跟的是異常對象;throw用在方法體內;

(2)throws:用於拋出異常類,後面跟的是異常類名,可以跟多個,用逗號隔開。throws用在方法上

(3)異常處理方式:拋出throws、捕捉try - catch - finally。

(4)什麽時候定義try,什麽時候定義throws?

    ①功能內部如果出現異常,如果可以處理,就用try;

    ②如果內部處理不了,就必須聲明出來,讓調用者處理。

45.編譯時異常和運行時異常的區別?

答:(1)編譯時異常在函數內被拋出,函數必須聲明,否則編譯失敗。

聲明的原因:是需要調用者對該異常進行處理。必須進行處理,否則無法編譯通過;(throws)

(2)運行時異常如果在函數內被拋出,在函數上不需要聲明。

不聲明的原因:不需要調用者處理,運行時異常發生,已經無法再讓程序繼續運行,所以,不讓調用處理的,直接讓程序停止,由調用者對代碼進行修正。(throw)

46.List、Set、Map是否繼承自Collection接口?

答:List、Set是,Map不是。Map是鍵值對映射容器,與List和Set有明顯的區別,而Set存儲的零散的元素且不允許有重復元素(數學中的集合也是如此),List是線性結構的容器,適用於按數值索引訪問元素的情形。

47.闡述ArrayList、Vector、LinkedList的存儲性能和特性?

答:(1)ArrayList:

①ArrayList底層是通過數組實現的,與LinkedList相比,查詢快,增刪慢;

②ArrayList的起始容量是10.當數組需要增長時,新的容量按如下公式獲得:新容量=(舊容量*3)/2+1,也就是說每一次容量大概會增長50%。

(2)Vector:

①Vector:底層也是通過數組實現的,與ArrayList相比,它是同步的,線程安全的;一般情況下:ArrayList適用於單線程,Vector適用於多線程。

②Vector的容量增長與“增長系數有關”,若指定了“增長系數”,且“增長系數有效(即,大於0)”;那麽,每次容量不足時,“新的容量”=“原始容量+增長系數”。若增長系數無效(即,小於/等於0),則“新的容量”=“原始容量x 2”。

(3)LinkedList:

①LinkedList底層是通過鏈表實現的,與ArrayList相比,查詢慢,增刪快;

②LinkedList在添加新元素時,先是在雙向鏈表中找到要插入節點的位置index;找到之後,再插入一個新節點。同時,雙向鏈表查找index位置的節點時,有一個加速動作:若index < 雙向鏈表長度的1/2,則從前向後查找;否則,從後向前查找。

48.簡述集合架構體系?

技術分享圖片

49.Collection和Collections的區別?

答:Collection是一個接口,它是Set、List等容器的父接口;Collections是個一個工具類,提供了一系列的靜態方法來輔助容器操作,這些方法包括對容器的搜索、排序、線程安全化等等。

50.List、Map、Set三個接口存取元素時,各有什麽特點?

答:(1)List以特定索引來存取元素,可以有重復元素。Set不能存放重復元素(用對象的equals()方法來區分元素是否重復)。

(2)Map保存鍵值對(key-value pair)映射,映射關系可以是一對一或多對一。

(3)Set和Map容器都有基於哈希存儲和排序樹的兩種實現版本,基於哈希存儲的版本理論存取時間復雜度為O(1),而基於排序樹版本的實現在插入或刪除元素時會按照元素或元素的鍵(key)構成排序樹從而達到排序和去重的效果。

51.TreeMap和TreeSet在排序時如何比較元素?Collections工具類中的sort()方法如何比較元素?

答:(1)TreeSet要求存放的對象所屬的類必須實現Comparable接口,該接口提供了比較元素的compareTo()方法,當插入元素時會回調該方法比較元素的大小。

(2)TreeMap要求存放的鍵值對映射的鍵必須實現Comparable接口從而根據鍵對元素進行排序。

(3)Collections工具類的sort方法有兩種重載的形式,第一種要求傳入的待排序容器中存放的對象比較實現Comparable接口以實現元素的比較;第二種不強制性的要求容器中的元素必須可比較,但是要求傳入第二個參數,參數是Comparator接口的子類型(需要重寫compare方法實現元素的比較),相當於一個臨時定義的排序規則,其實就是通過接口註入比較元素大小的算法,也是對回調模式的應用(Java中對函數式編程的支持)。

52、Thread類的wait( )和sleep( )的區別?

答:(1)所在類不同:wait( )是Object類中的方法;sleep( )是Tread類中的方法;

(2)slepp( )沒有釋放同步鎖,而wait( )釋放了同步鎖;

(3)slepp( )必須制定時間,而wait( )不用;

(4)slepp( )可以在任何地方使用,而wait( )、notify( )、notifyAll( )只能在同步方法或同步代碼塊中使用;

(5)slepp( )必須捕獲異常,而wait( )、notify( )、notifyAll( )不用;

53.線程的sleep()方法和yield()方法有什麽區別?

答:① sleep()方法給其他線程運行機會時不考慮線程的優先級,因此會給低優先級的線程以運行的機會;yield()方法只會給相同優先級或更高優先級的線程以運行的機會;

② 線程執行sleep()方法後轉入阻塞(blocked)狀態,而執行yield()方法後轉入就緒(ready)狀態;

③ sleep()方法聲明拋出InterruptedException,而yield()方法沒有聲明任何異常;

④ sleep()方法比yield()方法(跟操作系統CPU調度相關)具有更好的可移植性。

54.當一個線程進入一個對象的synchronized方法A之後,其它線程是否可進入此對象的synchronized方法B?

答:不能。其它線程只能訪問該對象的非同步方法,同步方法則不能進入。因為非靜態方法上的synchronized修飾符要求執行方法時要獲得對象的鎖,如果已經進入A方法說明對象鎖已經被取走,那麽試圖進入B方法的線程就只能在等鎖池(註意不是等待池哦)中等待對象的鎖。

55.簡述線程的五種狀態?

答:(1)新建(new):當一個線程處於新建狀態時,它僅僅是一個空的線程對象,系統不為它分配資源。Tread t = new Tread(new Runner());

(2)就緒(Runable):此時線程處在隨時可以運行的狀態,在隨後的任意時刻,都可能進入運行狀態。t.star( );

(3)運行(Running):處於這個狀態的線程占用CPU,執行程序代碼。

(4)阻塞(Blocked):阻塞狀態是指線程因為某些原因放棄CPU,暫時停止運行,直到線程重新進入就緒狀態。wait、sleep、同步鎖被占用;

(5)死亡(Dead):當線程退出run()方法時,就進入死亡狀態,該線程生命周期結束。可能正常執行完run()方法退出,也可能是遇到異常。

56.創建多線程的兩種方式期區別?

答:(1)第一種方式:繼承Thread類,由子類重寫run方法。步驟如下:

①定義類繼承Thread類;

②目的是重寫run方法,將要執行的代碼都存儲到run方法中;

③通過創建Thread類的子類對象,創建線程對象;

④調用線程的start方法,開啟線程,並執行run方法。

(2)第二種方式:實現Runnable接口。步驟如下:

①定義類實現Runnable接口。

②覆蓋接口中的run方法(用於封裝線程要運行的代碼)。

③通過Thread類創建線程對象;

④將實現了Runnable接口的子類對象作為實際參數傳遞給Thread類中的構造函數。

⑤調用Thread對象的start方法。開啟線程,並運行Runnable接口子類中的run方法。

(3)區別:

①繼承Thread :

好處:可以直接使用Tread類中的方法,代碼簡單;

弊端:如果該類已有父類,就不能用這種方法了;

②實現Runnable接口:

好處:可以避免單繼承的局限性,即使自己的線程類有父類也沒關系;

弊端:不能直接使用Tread類中的方法,要先獲取線程對象,代碼復雜。

57.synchronized關鍵字的用法?

答:synchronized關鍵字可以將對象或者方法標記為同步,以實現對對象和方法的互斥訪問,可以用synchronized(對象) { … }定義同步代碼塊,或者在聲明方法時將synchronized作為方法的修飾符。在第60題的例子中已經展示了synchronized關鍵字的用法。

58.舉例說明同步和異步。

答:如果系統中存在臨界資源(資源數量少於競爭資源的線程數量的資源),例如正在寫的數據以後可能被另一個線程讀到,或者正在讀的數據可能已經被另一個線程寫過了,那麽這些數據就必須進行同步存取(數據庫操作中的排他鎖就是最好的例子)。當應用程序在對象上調用了一個需要花費很長時間來執行的方法,並且不希望讓程序等待方法的返回時,就應該使用異步編程,在很多情況下采用異步途徑往往更有效率。事實上,所謂的同步就是指阻塞式操作,而異步就是非阻塞式操作。

59.啟動一個線程是調用run()還是start()方法?

答:啟動一個線程是調用start()方法,使線程所代表的虛擬處理機處於可運行狀態,這意味著它可以由JVM調度並執行,這並不意味著線程就會立即運行。run()方法是線程啟動後要進行回調(callback)的方法。

60.什麽是線程池(thread pool)?

答:在面向對象編程中,創建和銷毀對象是很費時間的,因為創建一個對象要獲取內存資源或者其它更多資源。在Java中更是如此,虛擬機將試圖跟蹤每一個對象,以便能夠在對象銷毀後進行垃圾回收。所以提高服務程序效率的一個手段就是盡可能減少創建和銷毀對象的次數,特別是一些很耗資源的對象創建和銷毀,這就是”池化資源”技術產生的原因。線程池顧名思義就是事先創建若幹個可執行的線程放入一個池(容器)中,需要的時候從池中獲取線程不用自行創建,使用完畢不需要銷毀線程而是放回池中,從而減少創建和銷毀線程對象的開銷。

【JAVA秒會技術之秒殺面試官】JavaSE常見面試題(三)