1. 程式人生 > 實用技巧 >88道Java學習筆記題,百事可樂,萬事芬達,心情雪碧,一週七喜,加油!

88道Java學習筆記題,百事可樂,萬事芬達,心情雪碧,一週七喜,加油!

這篇文章主要介紹了88道經典Java題及答案解析,文中通過示例程式碼介紹的非常詳細,對大家的學習或者面試複習具有一定的參考學習價值,內容過多可以先收藏慢慢觀看,需要的朋友們下面隨著小編來一起學習學習吧。

另外各位觀眾老爺覺得內容還可以的,請給個贊和評論,你的點贊和評論是我最大的動力,謝謝!

在這裡插入圖片描述

目錄

常見的Java問題

另外本人整理收藏了20年多家公司面試知識點整理,以及各種Java核心知識點免費分享給大家,我認為對面試來說是非常有用的,想要資料的話請點795983544

暗號CSDN。

在這裡插入圖片描述

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

Java虛擬機器是一個可以執行Java位元組碼的虛擬機器程序。Java原始檔被編譯成能被Java虛擬機器執行的位元組碼檔案。
Java被設計成允許應用程式可以執行在任意的平臺,而不需要程式設計師為每一個平臺單獨重寫或者是重新編譯。Java虛擬機器讓這個變為可能,因為它知道底層硬體平臺的指令長度和其他特性。

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

Java執行時環境(JRE)是將要執行Java程式的Java虛擬機器。它同時也包含了執行applet需要的瀏覽器外掛。Java開發工具包(JDK)是完整的Java軟體開發包,包含了JRE,編譯器和其他的工具(比如:JavaDoc,Java偵錯程式),可以讓開發者開發、編譯、執行Java應用程式。

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

“static”關鍵字表明一個成員變數或者是成員方法可以在沒有所屬的類的例項變數的情況下被訪問。
Java中static方法不能被覆蓋,因為方法覆蓋是基於執行時動態繫結的,而static方法是編譯時靜態繫結的。static方法跟類的任何例項都不相關,所以概念上不適用。

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

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

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

Java語言支援的8中基本資料型別是:

  • byte
  • short
  • int
  • long
  • float
  • double
  • boolean
  • char

自動裝箱是Java編譯器在基本資料型別和對應的物件包裝型別之間做的一個轉化。比如:把int轉化成Integer,double轉化成double,等等。反之就是自動拆箱。

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

Java中的方法過載發生在同一個類裡面兩個或者是多個方法的方法名相同但是引數不同的情況。與此相對,方法覆蓋是說子類重新定義了父類的方法。方法覆蓋必須有相同的方法名,引數列表和返回型別。覆蓋者可能不會限制它所覆蓋的方法的訪問。

7.Java中,什麼是建構函式?什麼是建構函式過載?什麼是複製建構函式?

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

8.Java支援多繼承麼?

不支援,Java不支援多繼承。每個類都只能繼承一個類,但是可以實現多個介面。

9.介面和抽象類的區別是什麼?

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

  • 介面中所有的方法隱含的都是抽象的。而抽象類則可以同時包含抽象和非抽象的方法。
  • 類可以實現很多個介面,但是隻能繼承一個抽象類
  • 類如果要實現一個介面,它必須要實現介面宣告的所有方法。但是,類可以不實現抽象類宣告的所有方法,當然,在這種情況下,類也必須得宣告成是抽象的。
  • 抽象類可以在不提供介面方法實現的情況下實現介面。
  • Java介面中宣告的變數預設都是final的。抽象類可以包含非final的變數。
  • Java介面中的成員函式預設是public的。抽象類的成員函式可以是private,protected或者是public。
  • 介面是絕對抽象的,不可以被例項化。抽象類也不可以被例項化,但是,如果它包含main方法的話是可以被呼叫的。
    也可以參考JDK8中抽象類和介面的區別

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

物件被值傳遞,意味著傳遞了物件的一個副本。因此,就算是改變了物件副本,也不會影響源物件的值。
物件被引用傳遞,意味著傳遞的並不是實際的物件,而是物件的引用。因此,外部對引用物件所做的改變會反映到所有的物件上。

Java執行緒

在這裡插入圖片描述

11.程序和執行緒的區別是什麼?

程序是執行著的應用程式,而執行緒是程序內部的一個執行序列。一個程序可以有多個執行緒。執行緒又叫做輕量級程序。

12.建立執行緒有幾種不同的方式?你喜歡哪一種?為什麼?

有三種方式可以用來建立執行緒:

  • 繼承Thread類
  • 實現Runnable介面
  • 應用程式可以使用Executor框架來建立執行緒池

實現Runnable介面這種方式更受歡迎,因為這不需要繼承Thread類。在應用設計中已經繼承了別的物件的情況下,這需要多繼承(而Java不支援多繼承),只能實現介面。同時,執行緒池也是非常高效的,很容易實現和使用。

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

執行緒在執行過程中,可以處於下面幾種狀態:

  • 就緒(Runnable):執行緒準備執行,不一定立馬就能開始執行。
  • 執行中(Running):程序正在執行執行緒的程式碼。
  • 等待中(Waiting):執行緒處於阻塞的狀態,等待外部的處理結束。
  • 睡眠中(Sleeping):執行緒被強制睡眠。
  • I/O阻塞(Blocked on I/O):等待I/O操作完成。
  • 同步阻塞(Blocked on Synchronization):等待獲取鎖。
  • 死亡(Dead):執行緒完成了執行。

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

在Java語言中,每一個物件有一把鎖。執行緒可以使用synchronized關鍵字來獲取物件上的鎖。synchronized關鍵字可應用在方法級別(粗粒度鎖)或者是程式碼塊級別(細粒度鎖)。

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

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

16.什麼是死鎖(deadlock)?

兩個程序都在等待對方執行完畢才能繼續往下執行的時候就發生了死鎖。結果就是兩個程序都陷入了無限的等待中。

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

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

Java集合類

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

集合類介面指定了一組叫做元素的物件。集合類介面的每一種具體的實現類都可以選擇以它自己的方式對元素進行儲存和排序。有的集合類允許重複的鍵,有些不允許。

Java集合類提供了一套設計良好的支援對一組物件進行操作的介面和類。Java集合類裡面最基本的介面有:

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

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

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

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

Iterator介面提供了很多對集合元素進行迭代的方法。每一個集合類都包含了可以返回迭代器例項的
迭代方法。迭代器可以在迭代的過程中刪除底層集合的元素。

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

下面列出了他們的區別:

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

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

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

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

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

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

Java中的HashMap使用hashCode()和equals()方法來確定鍵值對的索引,當根據鍵獲取值的時候也會用到這兩個方法。如果沒有正確的實現這兩個方法,兩個不同的鍵可能會有相同的hash值,因此,可能會被集合認為是相等的。而且,這兩個方法也用來發現重複元素。所以這兩個方法的實現對HashMap的精確性和正確性是至關重要的。

25.HashMap和Hashtable有什麼區別?

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

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

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

下面列出了Array和ArrayList的不同點:

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

27.ArrayList和LinkedList有什麼區別?

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

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

也可以參考ArrayList vs. LinkedList。

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

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

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

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

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

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

31.如何權衡是使用無序的陣列還是有序的陣列?

有序陣列最大的好處在於查詢的時間複雜度是O(log n),而無序陣列是O(n)。有序陣列的缺點是插入操作的時間複雜度是O(n),因為值大的元素需要往後移動來給新元素騰位置。相反,無序陣列的插入時間複雜度是常量O(1)。

32.Java集合類框架的最佳實踐有哪些?

根據應用的需要正確選擇要使用的集合的型別對效能非常重要,比如:假如元素的大小是固定的,而且能事先知道,我們就應該用Array而不是ArrayList。
有些集合類允許指定初始容量。因此,如果我們能估計出儲存的元素的數目,我們可以設定初始容量來避免重新計算hash值或者是擴容。
為了型別安全,可讀性和健壯性的原因總是要使用泛型。同時,使用泛型還可以避免執行時的ClassCastException。
使用JDK提供的不變類(immutable class)作為Map的鍵可以避免為我們自己的類實現hashCode()和equals()方法。
程式設計的時候介面優於實現。
底層的集合實際上是空的情況下,返回長度是0的集合或者是陣列,不要返回null。

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

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

34.HashSet和TreeSet有什麼區別?

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

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

垃圾回收的目的是識別並且丟棄應用不再使用的物件來釋放和重用資源。

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

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

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

在釋放物件佔用的記憶體之前,垃圾收集器會呼叫物件的finalize()方法。一般建議在該方法中釋放物件持有的資源。

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

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

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

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

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

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

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

當物件對當前使用這個物件的應用程式變得不可觸及的時候,這個物件就可以被回收了。

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

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

異常處理

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

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

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

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

45.throw和throws有什麼區別?

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

45.異常處理的時候,finally程式碼塊的重要性是什麼?(序號弄錯了,重改太麻煩了(—0—))

無論是否丟擲異常,finally程式碼塊總是會被執行。就算是沒有catch語句同時又丟擲異常的情況下,finally程式碼塊仍然會被執行。最後要說的是,finally程式碼塊主要用來釋放資源,比如:I/O緩衝區,資料庫連線。

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

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

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

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

Java小應用程式(Applet)

48.什麼是Applet?

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

49.解釋一下Applet的生命週期

applet可以經歷下面的狀態:

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

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

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

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

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

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

主要是由於安全的原因,給applet施加了以下的限制:

  • applet不能夠載入類庫或者定義本地方法。
  • applet不能在宿主機上讀寫檔案。
  • applet不能讀取特定的系統屬性。
  • applet不能發起網路連線,除非是跟宿主機。
  • applet不能夠開啟宿主機上其他任何的程式。

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

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

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

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

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

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

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

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

Servlet

57.什麼是Servlet?

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

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

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

59.Applet和Servlet有什麼區別?

Applet是執行在客戶端主機的瀏覽器上的客戶端Java程式。而Servlet是執行在web伺服器上的服務端的元件。applet可以使用使用者介面類,而Servlet沒有使用者介面,相反,Servlet是等待客戶端的HTTP請求,然後為請求產生響應。

60.GenericServlet和HttpServlet有什麼區別?

GenericServlet是一個通用的協議無關的Servlet,它實現了Servlet和ServletConfig介面。繼承自GenericServlet的Servlet應該要覆蓋service()方法。最後,為了開發一個能用在網頁上服務於使用HTTP協議請求的Servlet,你的Servlet必須要繼承自HttpServlet。這裡有Servlet的例子。

61.解釋下Servlet的生命週期。

對每一個客戶端的請求,Servlet引擎載入Servlet,呼叫它的init()方法,完成Servlet的初始化。然後,Servlet物件通過為每一個請求單獨呼叫service()方法來處理所有隨後來自客戶端的請求,最後,呼叫Servlet(譯者注:這裡應該是Servlet而不是server)的destroy()方法把Servlet刪除掉。

62.doGet()方法和doPost()方法有什麼區別?

  • doGet:GET方法會把名值對追加在請求的URL後面。因為URL對字元數目有限制,進而限制了用在客戶端請求的引數值的數目。並且請求中的引數值是可見的,因此,敏感資訊不能用這種方式傳遞。
  • doPOST:POST方法通過把請求引數值放在請求體中來克服GET方法的限制,因此,可以傳送的引數的數目是沒有限制的。最後,通過POST請求傳遞的敏感資訊對外部客戶端是不可見的。

63.什麼是Web應用程式?

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

64.什麼是服務端包含(Server Side Include)?

服務端包含(SSI)是一種簡單的解釋型服務端指令碼語言,大多數時候僅用在Web上,用servlet標籤嵌入進來。SSI最常用的場景把一個或多個檔案包含到Web伺服器的一個Web頁面中。當瀏覽器訪問Web頁面的時候,Web伺服器會用對應的servlet產生的文字來替換Web頁面中的servlet標籤。

65.什麼是Servlet鏈(Servlet Chaining)?

Servlet鏈是把一個Servlet的輸出傳送給另一個Servlet的方法。第二個Servlet的輸出可以傳送給第三個Servlet,依次類推。鏈條上最後一個Servlet負責把響應傳送給客戶端。

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

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

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

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

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

cookie是Web伺服器傳送給瀏覽器的一塊資訊。瀏覽器會在本地檔案中給每一個Web伺服器儲存cookie。以後瀏覽器在給特定的Web伺服器發請求的時候,同時會發送所有為該伺服器儲存的cookie。下面列出了session和cookie的區別:

  • 無論客戶端瀏覽器做怎麼樣的設定,session都應該能正常工作。客戶端可以選擇禁用cookie,但是,session仍然是能夠工作的,因為客戶端無法禁用服務端的session。
  • 在儲存的資料量方面session和cookies也是不一樣的。session能夠儲存任意的Java物件,cookie只能儲存String型別的物件。

69.瀏覽器和Servlet通訊使用的是什麼協議?

瀏覽器和Servlet通訊使用的是HTTP協議。

70.什麼是HTTP隧道?

HTTP隧道是一種利用HTTP或者是HTTPS把多種網路協議封裝起來進行通訊的技術。因此,HTTP協議扮演了一個打通用於通訊的網路協議的管道的包裝器的角色。把其他協議的請求掩蓋成HTTP的請求就是HTTP隧道。

71.sendRedirect()和forward()方法有什麼區別?

sendRedirect()方法會建立一個新的請求,而forward()方法只是把請求轉發到一個新的目標上。重定向(redirect)以後,之前請求作用域範圍以內的物件就失效了,因為會產生一個新的請求,而轉發(forwarding)以後,之前請求作用域範圍以內的物件還是能訪問的。一般認為sendRedirect()比forward()要慢。

72.什麼是URL編碼和URL解碼?

URL編碼是負責把URL裡面的空格和其他的特殊字元替換成對應的十六進位制表示,反之就是解碼。

Spring

73. 為什麼要使用 spring?

spring 提供 ioc 技術,容器會幫你管理依賴的物件,從而不需要自己建立和管理依賴物件了,更輕鬆的實現了程式的解耦。
spring 提供了事務支援,使得事務操作變的更加方便。
spring 提供了面向切片程式設計,這樣可以更方便的處理某一類的問題。
更方便的框架整合,spring 可以很方便的整合其他框架,比如 MyBatis、hibernate 等。

74. 解釋一下什麼是 aop?

aop 是面向切面程式設計,通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。
簡單來說就是統一處理某一“切面”(類)的問題的程式設計思想,比如統一處理日誌、異常等。

75. 解釋一下什麼是 ioc?

ioc:Inversionof Control(中文:控制反轉)是 spring 的核心,對於 spring 框架來說,就是由 spring 來負責控制物件的生命週期和物件間的關係。
簡單來說,控制指的是當前物件對內部成員的控制權;控制反轉指的是,這種控制權不由當前物件管理了,由其他(類,第三方容器)來管理。

76. spring 有哪些主要模組?

spring core:框架的最基礎部分,提供 ioc 和依賴注入特性。
spring context:構建於 core 封裝包基礎上的 context 封裝包,提供了一種框架式的物件訪問方法。
spring dao:Data Access Object 提供了JDBC的抽象層。
spring aop:提供了面向切面的程式設計實現,讓你可以自定義攔截器、切點等。
spring Web:提供了針對 Web 開發的整合特性,例如檔案上傳,利用 servlet listeners 進行 ioc 容器初始化和針對 Web 的 ApplicationContext。
spring Web mvc:spring 中的 mvc 封裝包提供了 Web 應用的 Model-View-Controller(MVC)的實現。

77. spring 常用的注入方式有哪些?

setter 屬性注入
構造方法注入
註解方式注入

78. spring 中的 bean 是執行緒安全的嗎?

spring 中的 bean 預設是單例模式,spring 框架並沒有對單例 bean 進行多執行緒的封裝處理。
實際上大部分時候 spring bean 無狀態的(比如 dao 類),所有某種程度上來說 bean 也是安全的,但如果 bean 有狀態的話(比如 view model 物件),那就要開發者自己去保證執行緒安全了,最簡單的就是改變 bean 的作用域,把“singleton”變更為“prototype”,這樣請求 bean 相當於 new Bean()了,所以就可以保證執行緒安全了。
有狀態就是有資料儲存功能。
無狀態就是不會儲存資料。

79. spring 支援幾種 bean 的作用域?

spring 支援 5 種作用域,如下:
singleton:spring ioc 容器中只存在一個 bean 例項,bean 以單例模式存在,是系統預設值;
prototype:每次從容器呼叫 bean 時都會建立一個新的示例,既每次 getBean()相當於執行 new Bean()操作;
Web 環境下的作用域:
request:每次 http 請求都會建立一個 bean;
session:同一個 http session 共享一個 bean 例項;
global-session:用於 portlet 容器,因為每個 portlet 有單獨的 session,globalsession 提供一個全域性性的 http session。
注意: 使用 prototype 作用域需要慎重的思考,因為頻繁建立和銷燬 bean 會帶來很大的效能開銷。

80. spring 自動裝配 bean 有哪些方式?

no:預設值,表示沒有自動裝配,應使用顯式 bean 引用進行裝配。
byName:它根據 bean 的名稱注入物件依賴項。
byType:它根據型別注入物件依賴項。
建構函式:通過建構函式來注入依賴項,需要設定大量的引數。
autodetect:容器首先通過建構函式使用 autowire 裝配,如果不能,則通過 byType 自動裝配。

81.Spring框架中都用到了哪些設計模式?

代理模式:在AOP和remoting中被用的比較多。

單例模式:在spring配置檔案中定義的bean預設為單例模式。

模板方法模式:用來解決程式碼重複的問題。

前端控制器模式:Spring提供了DispatcherServlet來對請求進行分發。

依賴注入模式:貫穿於BeanFactory / ApplicationContext介面的核心理念。

工廠模式:BeanFactory用來建立物件的例項。

82.你用過哪些重要的 Spring 註解?

@Controller - 用於 Spring MVC 專案中的控制器類。
@Service - 用於服務類。
@RequestMapping - 用於在控制器處理程式方法中配置 URI 對映。
@ResponseBody - 用於傳送 Object 作為響應,通常用於傳送 XML 或 JSON 資料作為響應。
@PathVariable - 用於將動態值從 URI 對映到處理程式方法引數。
@Autowired - 用於在 spring bean 中自動裝配依賴項。
@Qualifier - 使用 @Autowired 註解,以避免在存在多個 bean 型別例項時出現混淆。
@Scope - 用於配置 spring bean 的範圍。
@Configuration,@ComponentScan 和 @Bean - 用於基於 java 的配置。
@Aspect,@Before,@After,@Around,@Pointcut - 用於切面程式設計(AOP)。

82. 如何在 spring 中啟動註解裝配?

預設情況下,Spring 容器中未開啟註解裝配。因此,要使用基於註解裝配,我們必須通過配置 <context:annotation-config /> 元素在 Spring 配置檔案中啟用它。

83. @Component, @Controller, @Repository, @Service 有何區別?

@Component:這將 java 類標記為 bean。它是任何 Spring 管理元件的通用構造型。spring 的元件掃描機制現在可以將其拾取並將其拉入應用程式環境中。
@Controller:這將一個類標記為 Spring Web MVC 控制器。標有它的 Bean 會自動匯入到 IoC 容器中。
@Service:此註解是元件註解的特化。它不會對 @Component 註解提供任何其他行為。您可以在服務層類中使用 @Service 而不是 @Component,因為它以更好的方式指定了意圖。
@Repository:這個註解是具有類似用途和功能的 @Component 註解的特化。它為 DAO 提供了額外的好處。它將 DAO 匯入 IoC 容器,並使未經檢查的異常有資格轉換為 Spring DataAccessException。

84. @Required 註解有什麼用?

@Required 應用於 bean 屬性 setter 方法。此註解僅指示必須在配置時使用 bean 定義中的顯式屬性值或使用自動裝配填充受影響的 bean 屬性。如果尚未填充受影響的 bean 屬性,則容器將丟擲
BeanInitializationException。

JVM

85.什麼情況下會發生棧記憶體溢位?

1、棧是執行緒私有的,棧的生命週期和執行緒一樣,每個方法在執行的時候就會建立一個棧幀,它包含區域性變量表、運算元棧、動態連結、方法出口等資訊,區域性變量表又包括基本資料型別和物件的引用;
2、當執行緒請求的棧深度超過了虛擬機器允許的最大深度時,會丟擲StackOverFlowError異常,方法遞迴呼叫肯可能會出現該問題;

3、調整引數-xss去調整jvm棧的大小

86.詳解JVM記憶體模型?
在這裡插入圖片描述
jvm將虛擬機器分為5大區域,程式計數器、虛擬機器棧、本地方法棧、java堆、方法區;

  • 程式計數器:執行緒私有的,是一塊很小的記憶體空間,作為當前執行緒的行號指示器,用於記錄當前虛擬機器正在執行的執行緒指令地址;
  • 虛擬機器棧:執行緒私有的,每個方法執行的時候都會建立一個棧幀,用於儲存區域性變量表、運算元、動態連結和方法返回等資訊,當執行緒請求的棧深度超過了虛擬機器允許的最大深度時,就會丟擲StackOverFlowError;
  • 本地方法棧:執行緒私有的,儲存的是native方法的資訊,當一個jvm建立的執行緒呼叫native方法後,jvm不會在虛擬機器棧中為該執行緒建立棧幀,而是簡單的動態連結並直接呼叫該方法;
  • 堆:java堆是所有執行緒共享的一塊記憶體,幾乎所有物件的例項和陣列都要在堆上分配記憶體,因此該區域經常發生垃圾回收的操作;
  • 方法區:存放已被載入的類資訊、常量、靜態變數、即時編譯器編譯後的程式碼資料。即永久代,在jdk1.8中不存在方法區了,被元資料區替代了,原方法區被分成兩部分;
    1:載入的類資訊,2:執行時常量池;載入的類資訊被儲存在元資料區中,執行時常量池儲存在堆中;

87、JVM中一次完整的GC是什麼樣子的?物件如何晉升到老年代?

在這裡插入圖片描述
java堆 = 新生代+老年代;新生代 = Eden + Suivivor(S0 + S1),預設分配比例是8:1:1;當Eden區空間滿了的時候,就會觸發一次Minor GC,以收集新生代的垃圾,存活下來的物件會被分配到Survivor區大物件(需要大量連續記憶體空間的物件)會直接被分配到老年代如果物件在Eden中出生,並且在經歷過一次Minor GC之後仍然存活,被分配到存活區的話,年齡+1,此後每經歷過一次Minor GC並且存活下來,年齡就+1,當年齡達到15的時候,會被晉升到老年代;當老年代滿了,而無法容納更多物件的話,會觸發一次full gc;full gc儲存的是整個記憶體堆(包括年輕代和老年代);;Major GC是發生在老年代的GC,清理老年區,經常會伴隨至少一次minor gc;

88.Java中的垃圾回收演算法?

java中有四種垃圾回收演算法,分別是標記清除法、標記整理法、複製演算法、分代收集演算法;

  • 標記清除法:第一步:利用可達性去遍歷記憶體,把存活物件和垃圾物件進行標記;第二步:在遍歷一遍,將所有標記的物件回收掉;特點:效率不行,標記和清除的效率都不高;標記和清除後會產生大量的不連續的空間分片,可能會導致之後程式執行的時候需分配大物件而找不到連續分片而不得不觸發一次GC;
  • 標記整理法:第一步:利用可達性去遍歷記憶體,把存活物件和垃圾物件進行標記;第二步:將所有的存活的物件向一段移動,將端邊界以外的物件都回收掉;特點:適用於存活物件多,垃圾少的情況;需要整理的過程,無空間碎片產生;
  • 複製演算法:將記憶體按照容量大小分為大小相等的兩塊,每次只使用一塊,當一塊使用完了,就將還存活的物件移到另一塊上,然後在把使用過的記憶體空間移除;特點:不會產生空間碎片;記憶體使用率極低;
  • 分代收集演算法:根據記憶體物件的存活週期不同,將記憶體劃分成幾塊,java虛擬機器一般將記憶體分成新生代和老生代,在新生代中,有大量物件死去和少量物件存活,所以採用複製演算法,只需要付出少量存活物件的複製成本就可以完成收集;老年代中因為物件的存活率極高,沒有額外的空間對他進行分配擔保,所以採用標記清理或者標記整理演算法進行回收;

總結

目前就總結了這麼多,總體上有些題有點老了,不過還是可以學習看的。從基礎題到spring、JVM都是面試學習用到的,本人認為還是有很大作用的。這麼多可以先收藏,每天有時間可以看上一看,加強記憶。身為程式設計師最應該做的就是不斷的學習,時代在進步,只有學習才不會被淘汰,希望大家都加油,未來可期!!!

另外本人整理收藏了20年多家公司面試知識點整理 ,以及各種Java核心知識點免費分享給大家,我認為對面試來說是非常有用的,想要資料的話請點795983544 暗號CSDN。

在這裡插入圖片描述