標籤:複雜度 程式碼 原始碼 實現 類重寫 格式 run方法 覆蓋 相關
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常見面試題(三)