1. 程式人生 > >Java面試知識點總結(牛客網)

Java面試知識點總結(牛客網)

---------------------https://blog.csdn.net/u012456528/article/details/79759487?utm_source=copy

1. 什麼是Java虛擬機器?為什麼Java被稱作是“平臺無關的程式語言”?為什麼能跨平臺?

  • java虛擬機器是執行位元組碼檔案(.class)的虛擬機器程序。java源程式(.java)被編譯器編譯成位元組碼檔案(.class)。然後位元組碼檔案,將由java虛擬機器,解釋成機器碼(不同平臺的機器碼不同)。利用機器碼操作硬體和作業系統。
  • 因為不同的平臺裝有不同的JVM,它們能夠將相同的.class檔案,解釋成不同平臺所需要的機器碼。正是因為有JVM的存在,java被稱為平臺無關的程式語言。
  • 因為Java程式編譯之後的程式碼不是能被硬體系統直接執行的程式碼,而是一種“中間碼”——位元組碼。然後不同的硬體平臺上安裝有不同的Java虛擬機器(JVM),由JVM來把位元組碼再“翻譯”成所對應的硬體平臺能夠執行的程式碼

1.1 為什麼說java是解釋性靜態語言?

  • 編譯型語言:把做好的源程式全部編譯成二進位制程式碼,編譯後可直接執行程式。 執行速度快、效率高;依賴編譯器、跨平臺性差些。如C、C++、Delphi、Pascal,Fortran。 
  • 解釋型語言:把做好的源程式,需要一個解釋環境,翻譯一句然後執行一句。執行速度慢、效率低;依賴直譯器、跨平臺性好。如Java、Basic.
  • 動態語言Dynamically Typed Language:動態語言是指程式在執行時可以改變其結構:新的函式可以被引進,已有的函式可以被刪除等在結構上的變化。 動態語言的型別檢查是在執行時做的。 方便閱讀,不方便除錯。例如:JavaScript、Python、php 。
  • 靜態語言Statically Typed Language:在使用所有變數之前要宣告它們的資料型別。結構非常規範,便於除錯,方便型別安全。例如:C、C++、Java。

2.JDK和JRE的區別是什麼?

  • Java開發工具包(JDK)是完整的Java軟體開發包,包含了JRE,編譯器和其他的工具(比如:JavaDoc,Java偵錯程式),可以讓開發者開發、編譯、執行Java應用程式。
  • Java執行時環境(JRE)。它包括Java虛擬機器、Java核心類庫和支援檔案。它不包含開發工具(JDK)、編譯器、偵錯程式和其他工具。

3.”static”關鍵字是什麼意思?Java中是否可以覆蓋(override)一個private或者是static的方法?

  • “static”關鍵字表明一個成員變數或者是成員方法可以在沒有所屬的類的例項變數的情況下被訪問。 
    Java中static方法不能被覆蓋,因為方法覆蓋是基於執行時動態繫結的,而static方法是編譯時靜態繫結的。static方法跟類的任何例項都不相關,所以概念上不適用。
  • java中也不可以覆蓋private的方法,因為private修飾的變數和方法只能在當前類中使用,如果是其他的類繼承當前類是不能訪問到private變數或方法的,當然也不能覆蓋。

4.是否可以在static環境中訪問非static變數?

  • static變數在Java中是屬於類的,它在所有的例項中的值是一樣的。當類被Java虛擬機器載入的時候,會對static變數進行初始化。如果你的程式碼嘗試不用例項來訪問非static的變數,編譯器會報錯,因為這些變數還沒有被創建出來,還沒有跟任何例項關聯上。

5.Java支援的資料型別有哪些?什麼是自動拆裝箱?

  • Java支援的資料型別包括兩種:一種是基本資料型別,包含byte,char, short, boolean ,int, long, float, double;另一種是引用型別:如String等,其實是物件的引用,JVM中虛擬棧中存的是物件的地址,建立的物件實質在堆中,通過地址來找到堆中的物件的過程,即為引用型別。
  • 自動裝箱就是Java編譯器在基本資料型別和對應的物件包裝型別間的轉化,即int轉化為Integer,自動拆箱是Integer呼叫其方法將其轉化為int的過程。

6.Java中的方法覆蓋/重寫(Overriding)和方法過載(Overloading)是什麼意思?

  • Java中的方法過載發生在同一個類裡面兩個或者是多個方法的方法名相同但是引數不同的情況。過載Overloading是一個類中多型性的一種表現。
  • 方法覆蓋/重寫用在繼承中,子類重新定義了父類的方法。方法覆蓋必須有相同的方法名,引數列表和返回型別。覆蓋者可能不會限制它所覆蓋的方法的訪問。在java中,子類可繼承父類的方法,並做一定的修改,就採用方法重寫,又稱方法覆蓋。

7.Java中,什麼是構造方法?什麼是構造方法過載?什麼是複製構造方法?

  • 當新物件被建立的時候,構造方法會被呼叫。每一個類都有構造方法。在程式設計師沒有給類提供構造方法的情況下,Java編譯器會為這個類建立一個預設的構造方法。
  • Java中構造方法過載和方法過載很相似。可以為一個類建立多個構造方法。每一個構造方法必須有它自己唯一的引數列表。
  • Java不支援複製構造方法,如果你不自己寫構造方法的情況下,Java不會建立預設的複製構造方法。

8. Java支援多繼承麼?

Java中類不支援多繼承,只支援單繼承(即一個類只有一個父類)。但是java中的介面支援多繼承,,即一個子介面可以有多個父介面。(介面的作用是用來擴充套件物件的功能,一個子介面繼承多個父介面,說明子介面擴充套件了多個功能,當類實現介面時,類就擴充套件了相應的功能)。

從設計層面來說,抽象是對類的抽象,是一種模板設計,介面是行為的抽象,是一種行為的規範。

Java提供和支援建立抽象類和介面。它們的實現有共同點,不同點在於:

  • 介面和抽象類都不可以被例項化。類可以實現很個介面,但只能繼承個抽象類;
  • 介面由interface關鍵詞修飾,使用implements關鍵字實現,且必須要實現該介面的所有抽象方法
  • 抽象類中未實現方法用abstract修飾。,可以有非抽象的方法,main方法已實現的方法沒有抽象方法(HttpServlet)。
  • 介面中函式預設是public。抽象類的成員函式可以是private,protected或者是public;
  • 介面中變數預設是public static final的常量。抽象類可定義包含非final的變數;
  • 抽象類可以不繼承抽象類或不實現介面宣告的所有方法。
  • 抽象類可以在不提供介面方法實現的情況下實現介面

10. 什麼是值傳遞和引用傳遞?

一般認為,java內的傳遞都是值傳遞. java中例項物件的傳遞是引用傳遞。

  • 值傳遞是對基本型變數而言的,傳遞的是該變數的一個副本,改變副本不影響原變數;
  • 引用傳遞一般是對於物件型變數而言的,傳遞的是該物件地址的一個副本, 並不是原物件本身。

11. 程序與執行緒的區別?

  • 程序是執行著的應用程式,是系統進行資源分配和排程的一個獨立單位。執行緒是程序內部的一個執行序列,程序的一個實體,是CPU排程和分派的基本單位。
  • 程序之間相互獨立,通訊比較困難,包含固定的入口,執行順序,出口。執行緒之間共享一塊記憶體區域,不能佔有CPU、記憶體等資源,通訊比較方便,執行緒的入口執行順序這些過程被應用程式所控制,不能夠獨立執行。
  • 程序有獨立的地址空間,一個程序崩潰不會影響其它程序。執行緒有自己的堆疊和區域性變數,沒有單獨的地址空間,一個執行緒死掉就等於整個程序死掉。所以多程序的程式要比多執行緒的程式健壯,但耗費資源大效率差,但對於一些要求同時進行並且又要共享變數的併發操作,只能用執行緒,不能用程序。
  • 選擇執行緒:多核分佈、頻繁建立銷燬、大量計算、耗時的操作、並行操作
  • 選擇程序:多機分佈、穩定安全
  • 一個程式至少包括一個程序,一個程序至少包括一個執行緒。 

12. 建立執行緒有幾種不同的方式?

有四種方式可以用來建立執行緒。

  • 繼承Thread類,重寫run方法;
  • 實現Runnable介面,重寫run方法;
  • 應用程式可以使用Executor框架的ThreadPoolExecutor來建立執行緒池
  • 實現Callable介面,重寫call方法,可以丟擲異常,有返回值。

12.2 sleep和wait方法的區別

sleep()方法屬於Thread類中的。而wait()方法是屬於Object類中的。

sleep()方法,執行緒不會釋放物件鎖,程式暫停執行指定的時間,讓出cpu該其他執行緒,但是他的監控狀態依然保持者,當指定的時間到了又會自動恢復執行狀態。

而當呼叫wait()方法的時候,執行緒會放棄物件鎖,進入等待此物件的等待鎖定池,只有針對此物件呼叫notify()方法後本執行緒才進入物件鎖定池準備

13. 概括的解釋下執行緒的幾種可用狀態。

  • 新建( new ):新建立了一個執行緒物件。
  • 可執行( runnable ):執行緒物件建立後,其他執行緒(比如 main 執行緒)呼叫了該物件的start ()方法。該狀態的執行緒位於可執行執行緒池中,等待被執行緒排程選中,獲取cpu的使用權。
  • 執行( running ):可執行狀態( runnable )的執行緒獲得了cpu時間片( timeslice ),執行程式程式碼。
  • 阻塞( block ):阻塞狀態是指執行緒因為某種原因放棄了cpu使用權,也即讓出了cpu timeslice ,暫時停止執行。直到執行緒進入可執行( runnable )狀態,才有機會再次獲得 cpu timeslice 轉到執行( running )狀態。阻塞的情況分三種:

(一). 等待阻塞:執行( running )的執行緒執行 o.wait ()方法,JVM會把該執行緒放入等待佇列( waitting queue )中。

(二). 同步阻塞:執行( running )的執行緒在獲取物件的同步鎖時,若該同步鎖被別的執行緒佔用,則 JVM 會把該執行緒放入鎖池( lock pool )中。

(三). 其他阻塞: 執行( running )的執行緒執行Thread.sleep ( long ms )或 t.join ()方法,或者發出了 I/O 請求時,JVM會把該執行緒置為阻塞狀態。當 sleep ()狀態超時、join()等待執行緒終止或者超時、或者I/O 處理完畢時,執行緒重新轉入可執行( runnable )狀態。

  • 死亡( dead ):執行緒run()、 main() 方法執行結束,或者因異常退出了run()方法,則該執行緒結束生命週期。死亡的執行緒不可再次復生。 
    image

13.2  程序五狀態  

  • 新狀態:程序已經建立,還沒有申請到相應的資源   
  • 就緒態:程序做好了準備,只等待處理機   
  • 執行狀態:該程序正在執行(單處理機,某一時刻僅一個程序佔用處理機) 
  • 阻塞狀態:等待某事件發生才能執行,如等待I/O完成。
  • 終止狀態.

 

具有掛起狀態的程序狀態轉換

  • 就緒:程序在記憶體,準備執行
  • 阻塞:程序在記憶體,等待事件
  • 就緒/掛起:程序在外存,只要調入記憶體即可執行
  • 阻塞/掛起:程序在外存,等待事件。 

  •   阻    塞   →  阻塞/掛起:OS通常將阻塞程序換出,以騰出記憶體空間
  • 阻塞/掛起 →  就緒/掛起:當阻塞/掛起程序等待的事件發生時,可以將其轉換為就緒/掛起。
  • 就緒/掛起 →    就    緒  :OS需要調入一個程序執行。
  •   就    緒   →  就緒/掛起:一般,OS掛起阻塞程序。但是有時也會掛起就緒程序,釋放足夠的記憶體空間。
  •       新      →  就緒/掛起:新程序建立後若無足夠的記憶體分配,則插入到就緒/掛起佇列。

14. 同步方法和同步程式碼塊的區別是什麼?

為何使用同步? 
java允許多執行緒併發控制,當多個執行緒同時操作一個可共享的資源變數時(增刪改查),將會導致資料的不準確,相互之間產生衝突,因此加入同步鎖以避免在該執行緒沒有完成操作之前,被其他執行緒的呼叫,從而保證了該變數的唯一性和準確性。

區別

  • 同步方法預設用this或者當前類class物件作為鎖;
  • 同步程式碼塊可以選擇以什麼來加鎖,比同步方法要更細顆粒度,我們可以選擇只同步會發生同步問題的部分程式碼而不是整個方法;
  • 同步方法使用關鍵字 synchronized修飾方法,而同步程式碼塊主要是修飾需要進行同步的程式碼,用synchronized(object){程式碼內容}進行修飾;

15. 在監視器(Monitor)內部,是如何做執行緒同步的?程式應該做哪種級別的同步?

監視器和鎖在Java虛擬機器中是一塊使用的。監視器監視一塊同步程式碼塊,確保一次==只有一個執行緒執行同步程式碼塊==。每一個監視器都和一個物件引用相關聯。執行緒在獲取鎖之前不允許執行同步程式碼。

16.什麼是死鎖(deadlock)?

所謂死鎖是指多個進 程因==競爭資源==而造成的一種僵局(互相等待),若無外力作用,這些程序都將無法向前推進。死鎖產生的4個必要條件:

  • 互斥條件:程序要求對所分配的資源(如印表機)進行排他性控制,即在一段時間內某 資源僅為一個程序所佔有。此時若有其他程序請求該資源,則請求程序只能等待。
  • 不剝奪條件:程序所獲得的資源在未使用完畢之前,不能被其他程序強行奪走,即只能 由獲得該資源的程序自己來釋放(只能是主動釋放)。
  • 請求和保持條件:程序已經保持了至少一個資源,但又提出了新的資源請求,而該資源 已被其他程序佔有,此時請求程序被阻塞,但對自己已獲得的資源保持不放。
  • 迴圈等待條件:存在一種程序資源的==迴圈等待鏈==,鏈中每一個程序已獲得的資源同時被鏈中下一個程序所請求。

17. 如何確保N個執行緒可以訪問N個資源同時又不導致死鎖?

使用多執行緒的時候,一種非常簡單的避免死鎖的方式就是:==指定獲取鎖的順序==,並強制執行緒按照指定的順序獲取鎖。因此,如果所有的執行緒都是以同樣的順序加鎖和釋放鎖,就不會出現死鎖了。

18.Java集合類框架的基本介面有哪些?

集合類介面指定了一組叫做元素的物件。集合類介面的每一種具體的實現類都可以選擇以它自己的方式對元素進行儲存和排序。有的集合類允許重複的鍵,有些不允許。 
Java集合類提供了一套設計良好的支援對一組物件進行操作的介面和類。Java集合類裡面最基本的介面有:

  • Collection:代表一組物件,每一個物件都是它的子元素。
  • Set:不包含重複元素的Collection。
  • List:有順序的collection,並且可以包含重複元素。
  • Map:可以把鍵(key)對映到值(value)的物件,鍵不能重複。

19.為什麼集合類沒有實現Cloneable和Serializable介面?

克隆(cloning)或者是序列化(serialization)的語義和含義是跟具體的實現相關的。因此,應該由集合類的具體實現來決定如何被克隆或者是序列化。

20.什麼是迭代器(Iterator)?

 迭代器是一種設計模式,它是一個物件,它可以遍歷並選擇序列中的物件。

  •   使用iterator()要求容器返回一個Iterator。第一次呼叫Iterator的next()第一個元素。注意:iterator()方法是java.lang.Iterable介面,被Collection繼承。
  •   使用next()獲得序列中的下一個元素。
  •   使用hasNext()檢查序列中是否還有元素。
  •   使用remove()將迭代器新返回的元素刪除。

21.Iterator和ListIterator的區別是什麼?

下面列出了他們的區別:

  • Iterator可用來遍歷Set和List集合,但是ListIterator只能用來遍歷List。
  • Iterator對集合只能是前向遍歷,ListIterator既可以前向也可以後向。
  • ListIterator實現了Iterator介面,幷包含其他的功能,比如:增加元素,替換元素,獲取前一個和後一個元素的索引,等等。

22.快速失敗(fail-fast)和安全失敗(fail-safe)的區別是什麼?

Iterator的安全失敗是基於對底層集合做拷貝,因此,它不受源集合上修改的影響。java.util包下面的所有的集合類都是快速失敗的,而java.util.concurrent包下面的所有的類都是安全失敗的。快速失敗的迭代器會丟擲ConcurrentModificationException異常,而安全失敗的迭代器永遠不會丟擲這樣的異常

33.Java中的HashMap的工作原理是什麼?

Java中的HashMap是以鍵值對(key-value)的形式儲存元素的。HashMap需要一個hash函式,它使用hashCode()和equals()方法來從集合新增和檢索元素。當呼叫put()方法的時候,HashMap會計算key的hash值,然後把鍵值對儲存在集合中合適的索引上。如果key已經存在了,value會被更新成新值。HashMap的一些重要的特性是它的容量(capacity),負載因子(load factor)和擴容極限(threshold resizing)。

  • HashMap:它根據鍵的hashCode值儲存資料,大多數情況下可以直接定位到它的值,因而具有很快的訪問速度,但遍歷順序不確定的。 HashMap最多隻允許一條記錄的鍵為null,允許多條記錄的值為null。HashMap非執行緒安全,即任一時刻可以有多個執行緒同時寫HashMap,可能會導致資料的不一致。如果需要滿足執行緒安全,可以用 Collections的synchronizedMap方法使HashMap具有執行緒安全的能力,或者使用ConcurrentHashMap
  • Hashtable:Hashtable是遺留類,是執行緒安全的,但併發性不如ConcurrentHashMap
  • LinkedHashMap:LinkedHashMap是HashMap的一個子類,儲存了記錄的插入順序,在用Iterator遍歷LinkedHashMap時,先得到的記錄肯定是先插入的,也可以在構造時帶引數,按照訪問次序排序。
  • TreeMap:TreeMap實現SortedMap介面,能夠把它儲存的記錄根據鍵排序,預設是按鍵值的升序排序,也可以指定排序的比較器,當用Iterator遍歷TreeMap時,得到的記錄是排過序的。key必須實現Comparable介面或者在構造TreeMap傳入自定義的Comparator,否則會在執行時丟擲java.lang.ClassCastException型別的異常。 

34.hashCode()和equals()方法的重要性體現在什麼地方?

HashMap使用hashCode()和equals()方法來確定鍵值對的索引,根據鍵獲取值、發現重複元素的時候也會用到這兩個方法。

35.HashMap和Hashtable有什麼區別?

HashMap和Hashtable都實現了Map介面,因此很多特性非常相似。但是,他們有以下不同點:

  • HashMap允許鍵和值是null,而Hashtable不允許鍵或者值是null。
  • HashMap不是同步的,適合於單執行緒環境。而Hashtable是同步的,適合於多執行緒環境。
  • HashMap提供了可供應用迭代的鍵的集合,因此,HashMap是快速失敗的。另一方面,Hashtable提供了對鍵的列舉(Enumeration)。
  • 一般認為Hashtable是一個遺留的類。

36. 陣列(Array)和列表(ArrayList)有什麼區別?什麼時候應該使用Array而不是ArrayList?

  • Array可以包含基本型別和物件型別,ArrayList只能包含物件型別。
  • Array大小是固定的,ArrayList的大小是動態變化的。
  • ArrayList提供了更多的方法和特性,比如:addAll(),removeAll(),iterator()等等。
  • 對於基本型別資料,集合使用自動裝箱來減少編碼工作量。但是,當處理固定大小的基本資料型別的時候,這種方式相對比較慢。

37. ArrayList和LinkedList有什麼區別?

ArrayList和LinkedList都實現了List介面,他們有以下的不同點:

  • ArrayList是基於索引的資料介面,它的底層是陣列。它可以以O(1)時間複雜度對元素進行隨機訪問。與此對應,LinkedList是以==元素列表==的形式儲存它的資料,每一個元素都和它的前一個和後一個元素連結在一起,在這種情況下,查詢某個元素的時間複雜度是O(n)。 
    相對於ArrayList,LinkedList的插入,新增,刪除操作速度更快,因為當元素被新增到集合任意位置的時候,不需要像陣列那樣重新計算大小或者是更新索引。
  • LinkedList比ArrayList更佔記憶體,因為LinkedList為每一個節點儲存了兩個引用,一個指向前一個元素,一個指向下一個元素。

38.Comparable和Comparator介面是幹什麼的?列出它們的區別。

Java提供了只包含一個compareTo()方法的Comparable介面。這個方法可以個給兩個物件排序。具體來說,它返回負數,0,正數來表明已經存在的物件小於,等於,大於輸入物件。 
Java提供了包含compare()和equals()兩個方法的Comparator介面。compare()方法用來給兩個輸入引數排序,返回負數,0,正數表明第一個引數是小於,等於,大於第二個引數。equals()方法需要一個物件作為引數,它用來決定輸入引數是否和comparator相等。只有當輸入引數也是一個comparator並且輸入引數和當前comparator的排序結果是相同的時候,這個方法才返回true。

接:https://www.nowcoder.com/questionTerminal/99f7d1f4f8374e419a6d6924d35d9530 
來源:牛客網 
Comparable & Comparator 都是用來實現集合中元素的比較、排序的,只是 Comparable是在集合內部定義的方法實現的排序,Comparator 是在集合外部實現的排序,所以,如想實現排序,就需要在集合外定義 Comparator 介面的方法或在集合內實現 Comparable 介面的方法。 Comparator位於包java.util下,而Comparable位於包 java.lang下 Comparable 是一個物件本身就已經支援自比較所需要實現的介面(如 String、Integer 自己就可以完成比較大小操作,已經實現了Comparable介面) 自定義的類要在加入list容器中後能夠排序,可以實現Comparable介面,在用Collections類的sort方法排序時,如果不指定Comparator,那麼就以自然順序排序, 這裡的自然順序就是實現Comparable介面設定的排序方式。 而 Comparator 是一個專用的比較器,當這個物件不支援自比較或者自比較函式不能滿足你的要求時,你可以寫一個比較器來完成兩個物件之間大小的比較。 可以說一個是自已完成比較,一個是外部程式實現比較的差別而已。 用 Comparator 是策略模式(strategy design pattern),就是不改變物件自身,而用一個策略物件(strategy object)來改變它的行為。 比如:你想對整數採用絕對值大小來排序,Integer 是不符合要求的,你不需要去修改 Integer 類(實際上你也不能這麼做)去改變它的排序行為,只要使用一個實現了 Comparator 介面的物件來實現控制它的排序就行了。

39.什麼是Java優先順序佇列(Priority Queue)?

PriorityQueue是一個基於優先順序堆的無界佇列,它的元素是按照自然順序(natural order)排序的。在建立的時候,我們可以給它提供一個負責給元素排序的比較器。PriorityQueue不允許null值,因為他們沒有自然順序,或者說他們沒有任何的相關聯的比較器。最後,PriorityQueue不是執行緒安全的,入隊和出隊的時間複雜度是O(log(n))。

40.你瞭解大O符號(big-O notation)麼?你能給出不同資料結構的例子麼?

大O符號描述了當資料結構裡面的元素增加的時候,演算法的規模或者是一個漸進上界 。 
大O符號也可用來描述其他的行為,比如:記憶體消耗。因為集合類實際上是資料結構,我們一般使用大O符號基於時間,記憶體和效能來選擇最好的實現。大O符號可以對大量資料的效能給出一個很好的說明。

41.Enumeration介面和Iterator介面的區別有哪些?

Enumeration速度是Iterator的2倍,同時佔用更少的記憶體。但是,Iterator遠遠比Enumeration安全,因為其他執行緒不能夠修改正在被iterator遍歷的集合裡面的物件。同時,Iterator允許呼叫者刪除底層集合裡面的元素,這對Enumeration來說是不可能的。

42.HashSet和TreeSet有什麼區別?

  • HashSet是由一個hash表來實現的,因此,它的元素是無序的。add(),remove(),contains()方法的時間複雜度是O(1)。
  • 另一方面,TreeSet是由一個樹形的結構來實現的,它裡面的元素是有序的。因此,add(),remove(),contains()方法的時間複雜度是O(logn)。

43.Java中垃圾回收有什麼目的?什麼時候進行垃圾回收?

垃圾回收是在記憶體中存在沒有引用的物件或超過作用域的物件時進行。 
垃圾回收的目的是識別並且丟棄應用不再使用的物件來釋放和重用資源。

44.System.gc()和Runtime.gc()會做什麼事情?

這兩個方法用來提示JVM要進行垃圾回收。但是,立即開始還是延遲進行垃圾回收是取決於JVM的。

45.finalize()方法什麼時候被呼叫?解構函式(finalization)的目的是什麼?

垃圾回收器(garbage colector)決定回收某物件時,就會執行該物件的finalize()方法 但是在Java中很不幸,如果記憶體總是充足的,那麼垃圾回收可能永遠不會進行,也就是說filalize()可能永遠不被執行,顯然指望它做收尾工作是靠不住的。 那麼finalize()究竟是做什麼的呢?它最主要的用途是回收特殊渠道申請的記憶體。Java程式有垃圾回收器,所以一般情況下記憶體問題不用程式設計師操心。但有一種JNI(Java Native Interface)呼叫non-Java程式(C或C++),finalize()的工作就是回收這部分的記憶體。

呼叫時機:當垃圾回收器要宣告一個物件死亡時,至少要經過兩次標記過程:如果物件在進行可達性分析後發現沒有和GC Roots相連線的引用鏈,就會被第一次標記,並且判斷是否執行finalizer( )方法,如果物件覆蓋finalizer( )方法且未被虛擬機器呼叫過,那麼這個物件會被放置在F-Queue佇列中,並在稍後由一個虛擬機器自動建立的低優先順序的Finalizer執行緒區執行觸發finalizer( )方法,但不承諾等待其執行結束。 
finalization的目的:物件逃脫死亡的最後一次機會。(只要重新與引用鏈上的任何一個物件建立關聯即可。)但是不建議使用,執行代價高昂,不確定性大,且無法保證各個物件的呼叫順序。可用try-finally或其他替代。

46.如果物件的引用被置為null,垃圾收集器是否會立即釋放物件佔用的記憶體?

不會,在下一個垃圾回收週期中,這個物件將是可被回收的。

不會立即釋放物件佔用的記憶體。 如果物件的引用被置為null,只是斷開了當前執行緒棧幀中對該物件的引用關係,而 垃圾收集器是執行在後臺的執行緒,只有當用戶執行緒執行到安全點(safe point)或者安全區域才會掃描物件引用關係,掃描到物件沒有被引用則會標記物件,這時候仍然不會立即釋放該物件記憶體,因為有些物件是可恢復的(在 finalize方法中恢復引用 )。只有確定了物件無法恢復引用的時候才會清除物件記憶體。

47.Java堆的結構是什麼樣子的?什麼是堆中的永久代(Perm Gen space)?

JVM的堆是執行時資料區,所有類的例項和陣列都是在堆上分配記憶體。它在JVM啟動的時候被建立。物件所佔的堆記憶體是由自動記憶體管理系統也就是垃圾收集器回收。 
堆記憶體是由存活和死亡的物件組成的。存活的物件是應用可以訪問的,不會被垃圾回收。死亡的物件是應用不可訪問尚且還沒有被垃圾收集器回收掉的物件。一直到垃圾收集器把這些物件回收掉之前,他們會一直佔據堆記憶體空間。

永久代是用於存放靜態檔案,如Java類、方法等。持久代對垃圾回收沒有顯著影響,但是有些應用可能動態生成或者呼叫一些class,例如Hibernate 等,在這種時候需要設定一個比較大的持久代空間來存放這些執行過程中新增的類,永久代中一般包含: 
類的方法(位元組碼…) 
類名(Sring物件) 
.class檔案讀到的常量資訊 
class物件相關的物件列表和型別列表 (e.g., 方法物件的array). 
JVM建立的內部物件 
JIT編譯器優化用的資訊

48.序列(serial)收集器和吞吐量(throughput)收集器的區別是什麼?

吞吐量收集器使用並行版本的新生代垃圾收集器,它用於中等規模和大規模資料的應用程式。而序列收集器對大多數的小應用(在現代處理器上需要大概100M左右的記憶體)就足夠了。

49.在Java中,物件什麼時候可以被垃圾回收?

當一個物件到GC Roots不可達時,在下一個垃圾回收週期中嘗試回收該物件,如果該物件重寫了finalize()方法,並在這個方法中成功自救(將自身賦予某個引用),那麼這個物件不會被回收。但如果這個物件沒有重寫finalize()方法或者已經執行過這個方法,也自救失敗,該物件將會被回收。

50.JVM的永久代中會發生垃圾回收麼?

垃圾回收不會發生在永久代,如果永久代滿了或者是超過了臨界值,會觸發完全垃圾回收(Full GC)。如果你仔細檢視垃圾收集器的輸出資訊,就會發現永久代也是被回收的。這就是為什麼正確的永久代大小對避免Full GC是非常重要的原因。請參考下Java8:從永久代到元資料區 
(注:Java8中已經移除了永久代,新加了一個叫做元資料區的native記憶體區)

51.Java中的兩種異常型別是什麼?他們有什麼區別?

Java中有兩種異常:受檢查的(checked)異常和不受檢查的(unchecked)異常。不受檢查的異常不需要在方法或者是建構函式上宣告,就算方法或者是建構函式的執行可能會丟擲這樣的異常,並且不受檢查的異常可以傳播到方法或者是建構函式的外面。相反,受檢查的異常必須要用throws語句在方法或者是建構函式上宣告。這裡有Java異常處理的一些小建議。

Throwable包含了錯誤(Error)和異常(Excetion兩類) 
Exception又包含了執行時異常(RuntimeException, 又叫非檢查異常)和非執行時異常(又叫檢查異常) 
(1) Error是程式無法處理了, 如果OutOfMemoryError等, 這些異常發生時, java虛擬機器一般會終止執行緒 . 
(2) 執行時異常都是RuntimeException類及其子類,如 NullPointerException、IndexOutOfBoundsException等, 這些異常是不檢查的異常, 是在程式執行的時候可能會發生的, 所以程式可以捕捉, 也可以不捕捉. 這些錯誤一般是由程式的邏輯錯誤引起的, 程式應該從邏輯角度去儘量避免. 
(3) 檢查異常是執行時異常以外的異常, 也是Exception及其子類, 這些異常從程式的角度來說是必須經過捕捉檢查處理的, 否則不能通過編譯. 如IOException、SQLException等。

52.Java中Exception和Error有什麼區別?

Exception和Error都是Throwable的子類。Exception用於使用者程式可以捕獲的異常情況。Error定義了不期望被使用者程式捕獲的異常。

53.throw和throws有什麼區別?

throw關鍵字用來在程式中明確的丟擲異常,相反,throws語句用來表明方法不能處理的異常。每一個方法都必須要指定哪些異常不能處理,所以方法的呼叫者才能夠確保處理可能發生的異常,多個異常是用逗號分隔的。

1、Throw用於方法內部,Throws用於方法宣告上; 
2、Throw後跟異常物件,Throws後跟異常型別; 
3、Throw後只能跟一個異常物件,Throws後可以一次宣告多種異常型別。

54. 異常處理完成以後,Exception物件會發生什麼變化?、

Exception物件會在下一個垃圾回收過程中被回收掉。

55. finally程式碼塊和finalize()方法有什麼區別?

無論是否丟擲異常,finally程式碼塊都會執行,它主要是用來釋放應用佔用的資源。finalize()方法是Object類的一個protected方法,它是在物件被垃圾回收之前由Java虛擬機器來呼叫的。

56. 什麼是Applet?

java applet是能夠被包含在HTML頁面中並且能被啟用了java的客戶端瀏覽器執行的程式。Applet主要用來建立動態互動的web應用程式。

57. 解釋一下Applet的生命週期。

applet可以經歷下面的狀態: 
Init:每次被載入的時候都會被初始化。 
Start:開始執行applet。 
Stop:結束執行applet。 
Destroy:解除安裝applet之前,做最後的清理工作。

58. 當applet被載入的時候會發生什麼?

首先,建立applet控制類的例項,然後初始化applet,最後開始執行。

59. Applet和普通的Java應用程式有什麼區別?

applet是執行在啟用了java的瀏覽器中,Java應用程式是可以在瀏覽器之外執行的獨立的Java程式。但是,它們都需要有Java虛擬機器。 
進一步來說,Java應用程式需要一個有特定方法簽名的main函式來開始執行。Java applet不需要這樣的函式來開始執行。 
最後,Java applet一般會使用很嚴格的安全策略,Java應用一般使用比較寬鬆的安全策略。

60. Java applet有哪些限制條件?

主要是由於安全的原因,給applet施加了以下的限制: 
applet不能夠載入類庫或者定義本地方法;不能在宿主機上讀寫檔案;不能讀取特定的系統屬性;不能發起網路連線,除非是跟宿主機;不能夠開啟宿主機上其他任何的程式。

61. 什麼是不受信任的applet?

不受信任的applet是不能訪問或是執行本地系統檔案的Java applet,預設情況下,所有下載的applet都是不受信任的。

62. 從網路上載入的applet和從本地檔案系統載入的applet有什麼區別?

當applet是從網路上載入的時候,applet是由applet類載入器載入的,它受applet安全管理器的限制。 
當applet是從客戶端的本地磁碟載入的時候,applet是由檔案系統載入器載入的。 
從檔案系統載入的applet允許在客戶端讀檔案,寫檔案,載入類庫,並且也允許執行其他程式,但是,卻通不過位元組碼校驗。

63. applet類載入器是什麼?它會做哪些工作?

當applet是從網路上載入的時候,它是由applet類載入器載入的。類載入器有自己的java名稱空間等級結構。類載入器會保證來自檔案系統的類有唯一的名稱空間,來自網路資源的類有唯一的名稱空間。 
當瀏覽器通過網路載入applet的時候,applet的類被放置於和applet的源相關聯的私有的名稱空間中。然後,那些被類載入器載入進來的類都是通過了驗證器驗證的。驗證器會檢查類檔案格式是否遵守Java語言規範,確保不會出現堆疊溢位(stack overflow)或者下溢(underflow),傳遞給位元組碼指令的引數是正確的。

64. applet安全管理器是什麼?它會做哪些工作?

applet安全管理器是給applet施加限制條件的一種機制。瀏覽器可以只有一個安全管理器。安全管理器在啟動的時候被建立,之後不能被替換覆蓋或者是擴充套件。

65. 彈出式選擇選單(Choice)和列表(List)有什麼區別?

Choice是以一種緊湊的形式展示的,需要下拉才能看到所有的選項。Choice中一次只能選中一個選項。List同時可以有多個元素可見,支援選中一個或者多個元素。

66. 什麼是佈局管理器?

佈局管理器用來在容器中組織元件。

67. 滾動條(Scrollbar)和滾動面板(JScrollPane)有什麼區別?

Scrollbar是一個元件,不是容器。而ScrollPane是容器。ScrollPane自己處理滾動事件。

68. 哪些Swing的方法是執行緒安全的?

只有3個執行緒安全的方法: repaint(), revalidate(), and invalidate()。

69. 說出三種支援重繪(painting)的元件。

Canvas, Frame, Panel,和Applet支援重繪。

70. 什麼是JDBC?

JDBC是允許使用者在不同資料庫之間做選擇的一個抽象層。JDBC允許開發者用JAVA寫資料庫應用程式,而不需要關心底層特定資料庫的細節。

JDBC(Java DataBase Connectivity),是一套面向物件的應用程式介面(API),制定了統一的訪問各類關係資料庫的標準介面,為各個資料庫廠商提供了標準的實現。通過JDBC技術,開發人員可以用純Java語言和標準的SQL語句編寫完整的資料庫應用程式,並且真正地實現了軟體的跨平臺性。 
通常情況下使用JDBC完成以下操作: 
1.同資料庫建立連線; 
2.向資料庫傳送SQL語句; 
3.處理從資料庫返回的結果; 
JDBC具有下列優點: 
1.JDBC與ODBC(Open Database Connectivity,即開放資料庫互連)十分相似,便於軟體開發人員理解; 
2.JDBC使軟體開發人員從複雜的驅動程式編寫工作中解脫出來,可以完全專注於業務邏輯開發; 
3.JDBC支援多種關係型資料庫,大大增加了軟體的可移植性; 
4.JDBC API是面向物件的,軟體開發人員可以將常用的方法進行二次封裝,從而提高程式碼的重用性;

71. 資料庫連線池是什麼意思?

像開啟關閉資料庫連線這種和資料庫的互動可能是很費時的,尤其是當客戶端數量增加的時候,會消耗大量的資源,成本是非常高的。可以在應用伺服器啟動的時候建立很多個數據庫連線並維護在一個池中。連線請求由池中的連線提供。在連線使用完畢以後,把連線歸還到池中,以用於滿足將來更多的請求。

72. 讓RMI程式能正確執行有哪些步驟?

為了讓RMI程式能正確執行必須要包含以下幾個步驟: 
編譯所有的原始檔。 
使用rmic生成stub。 
啟動rmiregistry。 
啟動RMI伺服器。 
執行客戶端程式。

73. 解釋下Marshalling和demarshalling。

當應用程式希望把記憶體物件跨網路傳遞到另一臺主機或者是持久化到儲存的時候,就必須要把物件在記憶體裡面的表示轉化成合適的格式。這個過程就叫做Marshalling,反之就是demarshalling。

74. 解釋下Serialization和Deserialization。

Java提供了一種叫做物件序列化的機制,他把物件表示成一連串的位元組,裡面包含了物件的資料,物件的型別資訊,物件內部的資料的型別資訊等等。因此,序列化可以看成是為了把物件儲存在磁碟上或者是從磁碟上讀出來並重建物件而把物件扁平化的一種方式。反序列化是把物件從扁平狀態轉化成活動物件的相反的步驟。

75. 什麼是Servlet?

Servlet是用來處理客戶端請求併產生動態網頁內容的Java類。Servlet主要是用來處理或者是儲存HTML表單提交的資料,產生動態內容,在無狀態的HTTP協議下管理狀態資訊。

76. 說一下Servlet的體系結構。

所有的Servlet都必須要實現的核心的介面是javax.servlet.Servlet。每一個Servlet都必須要直接或者是間接實現這個介面,或者是繼承javax.servlet.GenericServlet或者javax.servlet.http.HTTPServlet。最後,Servlet使用多執行緒可以並行的為多個請求服務。

77. 什麼是Web應用程式?

Web應用程式是對Web或者是應用伺服器的動態擴充套件。有兩種型別的Web應用:面向表現的和麵向服務的。面向表現的Web應用程式會產生包含了很多種標記語言和動態內容的互動的web頁面作為對請求的響應。而面向服務的Web應用實現了Web服務的端點(endpoint)。一般來說,一個Web應用可以看成是一組安裝在伺服器URL名稱空間的特定子集下面的Servlet的集合。

78. 如何知道是哪一個客戶端的機器正在請求你的Servlet?

ServletRequest類可以找出客戶端機器的IP地址或者是主機名。getRemoteAddr()方法獲取客戶端主機的IP地址,getRemoteHost()可以獲取主機名。

79. HTTP響應的結構是怎麼樣的?

HTTP響應由三個部分組成: 
狀態碼(Status Code):描述了響應的狀態。可以用來檢查是否成功的完成了請求。請求失敗的情況下,狀態碼可用來找出失敗的原因。如果Servlet沒有返回狀態碼,預設會返回成功的狀態碼HttpServletResponse.SC_OK。 
HTTP頭部(HTTP Header):它們包含了更多關於響應的資訊。比如:頭部可以指定認為響應過期的過期日期,或者是指定用來給使用者安全的傳輸實體內容的編碼格式。如何在Serlet中檢索HTTP的頭部看這裡。 
主體(Body):它包含了響應的內容。它可以包含HTML程式碼,圖片,等等。主體是由傳輸在HTTP訊息中緊跟在頭部後面的資料位元組組成的。

80. 什麼是cookie?session和cookie有什麼區別?

cookie是Web伺服器傳送給瀏覽器的一塊資訊。瀏覽器會在本地檔案中給每一個Web伺服器儲存cookie。以後瀏覽器在給特定的Web伺服器發請求的時候,同時會發送所有為該伺服器儲存的cookie。下面列出了session和cookie的區別: 
無論客戶端瀏覽器做怎麼樣的設定,session都應該能正常工作。客戶端可以選擇禁用cookie,但是,session仍然是能夠工作的,因為客戶端無法禁用服務端的session。 
在儲存的資料量方面session和cookies也是不一樣的。session能夠儲存任意的Java物件,cookie只能儲存String型別的物件。

81. JSP請求是如何被處理的?

瀏覽器首先要請求一個以.jsp副檔名結尾的頁面,發起JSP請求,然後,Web伺服器讀取這個請求,使用JSP編譯器把JSP頁面轉化成一個Servlet類。需要注意的是,只有當第一次請求頁面或者是JSP檔案發生改變的時候JSP檔案才會被編譯,然後伺服器呼叫servlet類,處理瀏覽器的請求。一旦請求執行結束,servlet會把響應傳送給客戶端。

82. 封裝的定義和好處有哪些?

封裝給物件提供了隱藏內部特性和行為的能力。物件提供一些能被其他物件訪問的方法來改變它內部的資料。在Java當中,有3種修飾符:public,private和protected。每一種修飾符給其他的位於同一個包或者不同包下面物件賦予了不同的訪問許可權。 
下面列出了使用封裝的一些好處: 
通過隱藏物件的屬性來保護物件內部的狀態。 
提高了程式碼的可用性和可維護性,因為物件的行為可以被單獨的改變或者是擴充套件。 
禁止物件之間的不良互動提高模組化。 
參考這個文件獲取更多關於封裝的細節和示例。

或:

一是用private把類的細節與外界隔離起來,從而實現資料項和方法的隱藏,而要訪問這些資料項和方法唯一的途徑就是通過類本身,類才有資格呼叫它所擁有的資源(方法,資料項屬性等等)。所以第一個好處就是資料的安全性提高了。 
二是通過隱藏隔離,只允許外部對類做有限的訪問,開發者可以自由的改變類的內部實現,而無需修改使用該類的那些程式。只要那些在類外部就能被呼叫的方法保持其外部特徵不變,內部程式碼就可以自由改變,各取所需,利於分工。 
三就是提高了程式碼的重用性,封裝成工具類以後能夠減少很多繁瑣的步驟。

83.抽象的定義?抽象和封裝的不同點?

  • 抽象是把想法從具體的例項中分離出來的步驟,因此,要根據他們的功能而不是實現細節來建立類。Java支援建立只暴漏介面而不包含方法實現的抽象的類。這種抽象技術的主要目的是把類的行為和實現細節分離開。
  • 抽象和封裝是互補的概念。一方面,抽象關注物件的行為。另一方面,封裝關注物件行為的細節。一般是通過隱藏物件內部狀態資訊做到封裝,因此,封裝可以看成是用來提供抽象的一種策略。