最新最全的Java面試題整理(內附答案)

Java基礎知識篇

面向對象和麪向過程的區別

面向過程:html

  優勢:性能比面向對象高,由於類調用時須要實例化,開銷比較大,比較消耗資源;好比單片機、嵌入式開發、Linux/Unix等通常採用面向過程開發,性能是最重要的因素。java

缺點:沒有面向對象易維護、易複用、易擴展程序員

面向對象:web

  優勢:易維護、易複用、易擴展,因爲面向對象有封裝、繼承、多態性的特性,能夠設計出低耦合的系統,使系統更加靈活、更加易於維護面試

缺點:性能比面向過程低算法

Java語言有哪些特色?

  1,簡單易學;2,面向對象(封裝,繼承,多態);3,平臺無關性(Java虛擬機實現平臺無關性);4,可靠性;5,安全性;6,支持多線程(C++語言沒有內置的多線程機制,所以必須調用操做系統的多線程功能來進行多線程
程序設計,而Java語言卻提供了多線程支持);7,支持網絡編程而且很方便(Java語言誕生自己就是爲簡化網絡編程設計的,所以Java語言不只支持網絡編程並且很方便);8,編譯與解釋並存;數據庫

什麼是字節碼?採用字節碼的最大好處是什麼?什麼Java是虛擬機?

先看下java中的編譯器和解釋器:編程

  Java中引入了虛擬機的概念,即在機器和編譯程序之間加入了一層抽象的虛擬的機器。這臺虛擬的機器在任何平臺上都提供給編譯程序一個的共同的接口。編譯程序只須要面向虛擬機,生成虛擬機可以理解的代碼,而後由解釋器來將虛擬機代碼轉換爲特定系統的機器碼執行。在Java中,這種供虛擬機理解的代碼叫作字節碼(即擴展名爲.class的文件),它不面向任何特定的處理器,只面向虛擬機。每一種平臺的解釋器是不一樣的,可是實現的虛擬機是相同的。Java源程序通過編譯器編譯後變成字節碼,字節碼由虛擬機解釋執行,虛擬機將每一條要執行的字節碼送給解釋器,解釋器將其翻譯成特定機器上的機器碼,而後在特定的機器上運行,這就是上面提到的Java的特色的編譯與解釋並存的解釋。小程序

Java源代碼---->編譯器---->jvm可執行的Java字節碼(即虛擬指令)---->jvm---->jvm中解釋器----->機器可執行的二進制機器碼---->程序運行。
 

採用字節碼的好處:數組

  Java語言經過字節碼的方式,在必定程度上解決了傳統解釋型語言執行效率低的問題,同時又保留了解釋型語言可移植的特色。因此Java程序運行時比較高效,並且,因爲字節碼並不專對一種特定的機器,所以,Java程序無須從新編譯即可在多種不一樣的計算機上運行。

什麼是Java虛擬機

  任何一種能夠運行Java字節碼的軟件都可當作是Java的虛擬機(JVM)

什麼是Java程序的主類?應用程序和小程序的主類有何不一樣?

  一個程序中能夠有多個類,但只能有一個類是主類。在Java應用程序中,這個主類是指包含main()方法的類。而在Java小程序中,這個主類是一個繼承自系統類JApplet或Applet的子類。應用程序的主類不必定要求是public類,但小程序的主類要求必須是public類。主類是Java程序執行的入口點。

什麼是JDK?什麼是JRE?

  JDK: 顧名思義它是給開發者提供的開發工具箱,是給程序開發者用的。它除了包括完整的JRE(Java Runtime Environment),Java運行環境,還包含了其餘供開發者使用的工具包。

JDK

  JRE:普通用戶而只須要安裝JRE(Java Runtime Environment)來 來運行Java程序。而程序開發者必須安裝JDK來編譯、調試程序。

環境變量Path和ClassPath的做用是什麼?如何設置這兩個環境變量?

Java環境變量PATH和CLASSPATH - 簡書 http://www.jianshu.com/p/d63b099cf283

Java應用程序與小程序之間有那些差異?

簡單說應用程序是從主線程啓動(也就是main()方法)。applet小程序沒有main方法,主要是嵌在瀏覽器頁面上運行(調用init()線程或者run()來啓動),嵌入瀏覽器這點跟flash的小遊戲相似。

字符型常量和字符串常量的區別

1) 形式上:

字符常量是單引號引發的一個字符

字符串常量是雙引號引發的若干個字符

2) 含義上:

字符常量至關於一個整形值(ASCII值),能夠參加表達式運算

字符串常量表明一個地址值(該字符串在內存中存放位置)

3) 佔內存大小

字符常量只佔一個字節

字符串常量佔若干個字節(至少一個字符結束標誌)

Java語言採用何種編碼方案?有何特色?

  Java語言採用Unicode編碼標準,Unicode(標準碼),它爲每一個字符制訂了一個惟一的數值,所以在任何的語言,平臺,程序均可以放心的使用。

構造器Constructor是否可被override

  在講繼承的時候咱們就知道父類的私有屬性和構造方法並不能被繼承,因此Constructor也就不能被override,可是能夠overload,因此你能夠看到一個類中有多個構造函數的狀況。

重載和重寫的區別

  重載:發生在同一個類中,方法名必須相同,參數類型不一樣、個數不一樣、順序不一樣,方法返回值和訪問修飾符能夠不一樣,發生在編譯時。

  重寫:發生在父子類中,方法名、參數列表必須相同,返回值小於等於父類,拋出的異常小於等於父類,訪問修飾符大於等於父類;若是父類方法訪問修飾符爲private則子類中就不是重寫。

java 面向對象編程三大特性------封裝、繼承、多態

http://www.javashuo.com/article/p-abefjthy-by.html

String和StringBuffer、StringBuilder的區別是什麼?String爲何是不可變的?

可變性
 

String類中使用字符數組保存字符串,private final char value[],因此string對象是不可變的。StringBuilder與StringBuffer都繼承自AbstractStringBuilder類,在AbstractStringBuilder中也是使用字符數組保存字符串,char[]value,這兩種對象都是可變的。
  

線程安全性

String中的對象是不可變的,也就能夠理解爲常量,線程安全。AbstractStringBuilder是StringBuilder與StringBuffer的公共父類,定義了一些字符串的基本操做,如expandCapacity、append、insert、indexOf等公共方法。StringBuffer對方法加了同步鎖或者對調用的方法加了同步鎖,因此是線程安全的。StringBuilder並無對方法進行加同步鎖,因此是非線程安全的。
  

性能

每次對String 類型進行改變的時候,都會生成一個新的String對象,而後將指針指向新的String 對象。StringBuffer每次都會對StringBuffer對象自己進行操做,而不是生成新的對象並改變對象引用。相同狀況下使用StirngBuilder 相比使用StringBuffer 僅能得到10%~15% 左右的性能提高,但卻要冒多線程不安全的風險。

對於三者使用的總結:

若是要操做少許的數據用 = String

單線程操做字符串緩衝區 下操做大量數據 = StringBuilder

多線程操做字符串緩衝區 下操做大量數據 = StringBuffer

自動裝箱與拆箱

裝箱:將基本類型用它們對應的引用類型包裝起來;

拆箱:將包裝類型轉換爲基本數據類型;
  

Java使用自動裝箱和拆箱機制,節省了經常使用數值的內存開銷和建立對象的開銷,提升了效率,由編譯器來完成,編譯器會在編譯期根據語法決定是否進行裝箱和拆箱動做。

類、方法、成員變量和局部變量的可用修飾符 -

http://blog.csdn.net/yttcjj/article/details/6939239

在一個靜態方法內調用一個非靜態成員爲何是非法的?

  因爲靜態方法能夠不經過對象進行調用,所以在靜態方法裏,不能調用其餘非靜態變量,也不能夠訪問非靜態變量成員。

在Java中定義一個不作事且沒有參數的構造方法的做用

  Java程序在執行子類的構造方法以前,若是沒有用super()來調用父類特定的構造方法,則會調用父類中「沒有參數的構造方法」。所以,若是父類中只定義了有參數的構造方法,而在子類的構造方法中又沒有用super()來調用父類中特定的構造方法,則編譯時將發生錯誤,由於Java程序在父類中找不到沒有參數的構造方法可供執行。解決辦法是在父類里加上一個不作事且沒有參數的構造方法。

import java和javax有什麼區別

http://www.cnblogs.com/EasonJim/p/6993139.html

接口和抽象類的區別是什麼?

1.接口的方法默認是public,全部方法在接口中不能有實現,抽象類能夠有非抽象的方法

2.接口中的實例變量默認是final類型的,而抽象類中則不必定

3.一個類能夠實現多個接口,但最多隻能實現一個抽象類

4.一個類實現接口的話要實現接口的全部方法,而抽象類不必定

5.接口不能用new實例化,但能夠聲明,可是必須引用一個實現該接口的對象

從設計層面來講,抽象是對類的抽象,是一種模板設計,接口是行爲的抽象,是一種行爲的規範。

成員變量與局部變量的區別有那些?

  1. 從語法形式上,當作員變量是屬於類的,而局部變量是在方法中定義的變量或是方法的參數;成員變量能夠被public,private,static等修飾符所修飾,而局部變量不能被訪問控制修飾符及static所修飾;成員變量和局部變量都能被final所修飾;

  2. 從變量在內存中的存儲方式來看,成員變量是對象的一部分,而對象存在於堆內存,局部變量存在於棧內存

  3. 從變量在內存中的生存時間上看,成員變量是對象的一部分,它隨着對象的建立而存在,而局部變量隨着方法的調用而自動消失。

  4. 成員變量若是沒有被賦初值,則會自動以類型的默認值而賦值(一種狀況例外被final修飾但沒有被static修飾的成員變量必須顯示地賦值);而局部變量則不會自動賦值。

建立一個對象用什麼運算符?對象實體與對象引用有何不一樣?

  new運算符,new建立對象實例(對象實例在堆內存中),對象引用指向對象實例(對象引用存放在棧內存中)。一個對象引用能夠指向0個或1個對象(一根繩子能夠不繫氣球,也能夠系一個氣球);一個對象能夠有n個引用指向它(能夠用n條繩子繫住一個氣球)

什麼是方法的返回值?返回值在類的方法裏的做用是什麼?

  方法的返回值是指咱們獲取到的某個方法體中的代碼執行後產生的結果!(前提是該方法可能產生結果)。返回值的做用:接收出結果,使得它能夠用於其餘的操做!

一個類的構造方法的做用是什麼?若一個類沒有聲明構造方法,改程序能正確執行嗎?爲何?

  主要做用是完成對類對象的初始化工做。能夠執行。由於一個類即便沒有聲明構造方法也會有默認的不帶參數的構造方法。

構造方法有哪些特性?

  1,名字與類名相同;2,沒有返回值,但不能用void聲明構造函數;3,生成類的對象時自動執行,無需調用。

靜態方法和實例方法有何不一樣?

靜態方法和實例方法的區別主要體如今兩個方面:

  1. 在外部調用靜態方法時,可使用"類名.方法名"的方式,也可使用"對象名.方法名"的方式。而實例方法只有後面這種方式。也就是說,調用靜態方法能夠無需建立對象。

  2. 靜態方法在訪問本類的成員時,只容許訪問靜態成員(即靜態成員變量和靜態方法),而不容許訪問實例成員變量和實例方法;實例方法則無此限制

對象的相等與指向他們的引用相等,二者有什麼不一樣?

  對象的相等 比的是內存中存放的內容是否相等而 引用相等 比較的是他們指向的內存地址是否相等。

在調用子類構造方法以前會先調用父類沒有參數的構造方法,其目的是?

  幫助子類作初始化工做。

什麼是多態機制?Java語言是如何實現多態的?

http://blog.csdn.net/bornlili/article/details/55213563

equals 和 == 的區別?

通俗點講:==是看看左右是否是一個東西。equals是看看左右是否是長得同樣。如何記住嘛。若是單純是想記住,==:等於。equals:相同。兩個長得同樣的人,只能說長的相同(equals),可是不等於他們倆是一我的。你只要記住equals,==就不用記了。

術語來說的區別:1.==是判斷兩個變量或實例是否是指向同一個內存空間 equals是判斷兩個變量或實例所指向的內存空間的值是否是相同
2.==是指對內存地址進行比較 equals()是對字符串的內容進行比較3.==指引用是否相同 equals()指的是值是否相同

建立線程有幾種不一樣的方式?你喜歡哪種?爲何?

  1. 繼承Thread類
  2. 實現Runnable接口
  3. 應用程序可使用Executor框架來建立線程池
  4. 實現Callable接口。

我更喜歡實現Runnable接口這種方法,固然這也是如今大多程序員會選用的方法。由於一個類只能繼承一個父類而能夠實現多個接口。同時,線程池也是很是高效的,很容易實現和使用。

簡述線程,程序、進程的基本概念。以及他們之間關係是什麼?(參考書籍:《Java程序設計基礎》第五版)

線程與進程類似,但線程是一個比進程更小的執行單位。一個進程在其執行的過程當中能夠產生多個線程。與進程不一樣的是同類的多個線程共享同一塊內存空間和一組系統資源,因此係統在產生一個線程,或是在各個線程之間做切換工做時,負擔要比進程小得多,也正由於如此,線程也被稱爲輕量級進程。

程序是含有指令和數據的文件,被存儲在磁盤或其餘的數據存儲設備中,也就是說程序是靜態的代碼。

進程是程序的一次執行過程,是系統運行程序的基本單位,所以進程是動態的。系統運行一個程序便是一個進程從建立,運行到消亡的過程。簡單來講,一個進程就是一個執行中的程序,它在計算機中一個指令接着一個指令地執行着,同時,每一個進程還佔有某些系統資源如CPU時間,內存空間,文件,文件,輸入輸出設備的使用權等等。換句話說,當程序在執行時,將會被操做系統載入內存中。
線程是進程劃分紅的更小的運行單位。線程和進程最大的不一樣在於基本上各進程是獨立的,而各線程則不必定,由於同一進程中的線程極有可能會相互影響。從另外一角度來講,進程屬於操做系統的範疇,主要是同一段時間內,能夠同時執行一個以上的程序,而線程則是在同一程序內幾乎同時執行一個以上的程序段。

什麼是多線程?爲何程序的多線程功能是必要的?

多線程就是幾乎同時執行多個線程(一個處理器在某一個時間點上永遠都只能是一個線程!即便這個處理器是多核的,除非有多個處理器才能實現多個線程同時運行。)。幾乎同時是由於實際上多線程程序中的多個線程其實是一個線程執行一會而後其餘的線程再執行,並非不少書籍所謂的同時執行。這樣能夠帶來如下的好處:

  1. 使用線程能夠把佔據長時間的程序中的任務放到後臺去處理
  2. 用戶界面能夠更加吸引人,這樣好比用戶點擊了一個按鈕去觸發某些事件的處理,能夠彈出一個進度條來顯示處理的進度
  3. 程序的運行速度可能加快
  4. 在一些等待的任務實現上如用戶輸入、文件讀寫和網絡收發數據等,線程就比較有用了。在這種狀況下能夠釋放一些珍貴的資源如內存佔用等等。
    還有其餘不少使用多線程的好處,這裏就不一一說明了。

多線程與多任務的差別是什麼?(參考書籍:《Java程序設計基礎》第五版)

多任務與多線程是兩個不一樣的概念,
多任務是針對操做系統而言的,表示操做系統能夠同時運行多個應用程序。
而多線程是針對一個進程而言的,表示在一個進程內部能夠幾乎同時執行多個線程

線程有哪些基本狀態?這些狀態是如何定義的?

  1. 新建(new):新建立了一個線程對象。
  2. 可運行(runnable):線程對象建立後,其餘線程(好比main線程)調用了該對象的start()方法。該狀態的線程位於可運行線程池中,等待被線程調度選中,獲 取cpu的使用權。
  3. 運行(running):可運行狀態(runnable)的線程得到了cpu時間片(timeslice),執行程序代碼。
  4. 阻塞(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)狀態。
  5. 死亡(dead):線程run()、main()方法執行結束,或者因異常退出了run()方法,則該線程結束生命週期。死亡的線程不可再次復生。

線程的基本狀態

備註:
能夠用早起坐地鐵來比喻這個過程:
還沒起牀:sleeping
起牀收拾好了,隨時能夠坐地鐵出發:Runnable
等地鐵來:Waiting
地鐵來了,但要排隊上地鐵:I/O阻塞
上了地鐵,發現暫時沒座位:synchronized阻塞
地鐵上找到座位:Running
到達目的地:Dead

什麼是線程的同步?程序中爲何要實現線程的同步?是如何實現同步的?

當一個線程對共享的數據進行操做時,應使之成爲一個」原子操做「,即在沒有完成相關操做以前,不容許其餘線程打斷它,不然,就會破壞數據的完整性,必然會獲得錯誤的處理結果,這就是線程的同步。
在多線程應用中,考慮不一樣線程之間的數據同步和防止死鎖。當兩個或多個線程之間同時等待對方釋放資源的時候就會造成線程之間的死鎖。爲了防止死鎖的發生,須要經過同步來實現線程安全。

在監視器(Monitor)內部,是如何作線程同步的?程序應該作哪一種級別的同步?

在 java 虛擬機中, 每一個對象( Object 和 class )經過某種邏輯關聯監視器,每一個監視器和一個對象引用相關聯, 爲了實現監視器的互斥功能, 每一個對象都關聯着一把鎖.
一旦方法或者代碼塊被 synchronized 修飾, 那麼這個部分就放入了監視器的監視區域, 確保一次只能有一個線程執行該部分的代碼, 線程在獲取鎖以前不容許執行該部分的代碼
另外 java 還提供了顯式監視器( Lock )和隱式監視器( synchronized )兩種鎖方案

什麼是死鎖(deadlock)?

360百科

死鎖 :是指兩個或兩個以上的進程在執行過程當中,因爭奪資源而形成的一種互相等待的現象,若無外力做用,它們都將沒法推動下去 。
產生緣由:

  • 由於系統資源不足。
  • 進程運行推動順序不合適。
  • 資源分配不當等。
  • 佔用資源的程序崩潰等。

若是系統資源充足,進程的資源請求都可以獲得知足,死鎖出現的可能性就很低,不然就會因爭奪有限的資源而陷入死鎖。其次,進程運行推動順序與速度不一樣,也可能產生死鎖。

下面四個條件是死鎖的必要條件,只要系統發生死鎖,這些條件必然成立,而只要下列條件之一不知足,就不會發生死鎖。

  • 互斥條件:一個資源每次只能被一個進程使用。
  • 請求與保持條件:一個進程因請求資源而阻塞時,對已得到的資源保持不放。
  • 不剝奪條件:進程已得到的資源,在末使用完以前,不能強行剝奪。
  • 循環等待條件:若干進程之間造成一種頭尾相接的循環等待資源關係。
    死鎖的解除與預防:

理解了死鎖的緣由,尤爲是產生死鎖的四個必要條件,就能夠最大可能地避免、預防和 解除死鎖。因此,在系統設計、進程調度等方面注意如何不讓這四個必要條件成立,如何確 定資源的合理分配算法,避免進程永久佔據系統資源。此外,也要防止進程在處於等待狀態的狀況下佔用資源。所以,對資源的分配要給予合理的規劃。

如何確保N個線程能夠訪問N個資源同時又不致使死鎖?

上面一題咱們知道了發生死鎖的四個必要條件。咱們只要使其中一個不成立就好了。一種很是簡單的避免死鎖的方式就是:指定獲取鎖的順序,並強制線程按照指定的順序獲取鎖。所以,若是全部的線程都是以一樣的順序加鎖和釋放鎖,就不會出現死鎖了。這也就是破壞了第四個條件循環等待條件。

Java中垃圾回收有什麼目的?何時進行垃圾回收?

垃圾回收是在內存中存在沒有引用的對象或超過做用域的對象時進行。

垃圾回收的目的是識別而且丟棄應用再也不使用的對象來釋放和重用資源。

finalize()方法何時被調用?析構函數(finalization)的目的是什麼?

1)垃圾回收器(garbage colector)決定回收某對象時,就會運行該對象的finalize()方法;
finalize是Object類的一個方法,該方法在Object類中的聲明protected void finalize() throws Throwable { }
在垃圾回收器執行時會調用被回收對象的finalize()方法,能夠覆蓋此方法來實現對其資源的回收。注意:一旦垃圾回收器準備釋放對象佔用的內存,將首先調用該對象的finalize()方法,而且下一次垃圾回收動做發生時,才真正回收對象佔用的內存空間

2)GC原本就是內存回收了,應用還須要在finalization作什麼呢? 答案是大部分時候,什麼都不用作(也就是不須要重載)。只有在某些很特殊的狀況下,好比你調用了一些native的方法(通常是C寫的),能夠要在finaliztion裏去調用C的釋放函數。

若是對象的引用被置爲null,垃圾收集器是否會當即釋放對象佔用的內存?

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

JavaWeb基礎知識總結

Servlet總結:

在Java Web程序中,Servlet主要負責接收用戶請求HttpServletRequest,在doGet(),doPost()中作相應的處理,並將迴應HttpServletResponse反饋給用戶。Servlet能夠設置初始化參數,供Servlet內部使用。一個Servlet類只會有一個實例,在它初始化時調用init()方法,銷燬時調用destroy()方法Servlet須要在web.xml中配置(MyEclipse中建立Servlet會自動配置),一個Servlet能夠設置多個URL訪問Servlet不是線程安全,所以要謹慎使用類變量。

闡述Servlet和CGI的區別?

CGI的不足之處:

1,須要爲每一個請求啓動一個操做CGI程序的系統進程。若是請求頻繁,這將會帶來很大的開銷。

2,須要爲每一個請求加載和運行一個CGI程序,這將帶來很大的開銷

3,須要重複編寫處理網絡協議的代碼以及編碼,這些工做都是很是耗時的。

Servlet的優勢:

1,只須要啓動一個操做系統進程以及加載一個JVM,大大下降了系統的開銷

2,若是多個請求須要作一樣處理的時候,這時候只須要加載一個類,這也大大下降了開銷

3,全部動態加載的類能夠實現對網絡協議以及請求解碼的共享,大大下降了工做量。

4,Servlet能直接和Web服務器交互,而普通的CGI程序不能。Servlet還能在各個程序之間共享數據,使數據庫鏈接池之類的功能很容易實現。

補充:Sun Microsystems公司在1996年發佈Servlet技術就是爲了和CGI進行競爭,Servlet是一個特殊的Java程序,一個基於Java的Web應用一般包含一個或多個Servlet類。Servlet不可以自行建立並執行,它是在Servlet容器中運行的,容器將用戶的請求傳遞給Servlet程序,並將Servlet的響應回傳給用戶。一般一個Servlet會關聯一個或多個JSP頁面。之前CGI常常由於性能開銷上的問題被詬病,然而Fast CGI早就已經解決了CGI效率上的問題,因此面試的時候大可沒必要信口開河的詬病CGI,事實上有不少你熟悉的網站都使用了CGI技術。

參考:《javaweb整合開發王者歸來》P7

Servlet接口中有哪些方法及Servlet生命週期探祕

Servlet接口定義了5個方法,其中前三個方法與Servlet生命週期相關

  • void init(ServletConfig config) throws ServletException
  • void service(ServletRequest req, ServletResponse resp) throws ServletException, java.io.IOException
  • void destory()
  • java.lang.String getServletInfo()
  • ServletConfig getServletConfig()

生命週期: Web容器加載Servlet並將其實例化後,Servlet生命週期開始,容器運行其init()方法進行Servlet的初始化;請求到達時調用Servlet的service()方法,service()方法會根據須要調用與請求對應的doGet或doPost等方法;當服務器關閉或項目被卸載時服務器會將Servlet實例銷燬,此時會調用Servlet的destroy()方法init方法和destory方法只會執行一次,service方法客戶端每次請求Servlet都會執行。Servlet中有時會用到一些須要初始化與銷燬的資源,所以能夠把初始化資源的代碼放入init方法中,銷燬資源的代碼放入destroy方法中,這樣就不須要每次處理客戶端的請求都要初始化與銷燬資源。

參考:《javaweb整合開發王者歸來》P81

get和post請求的區別?

①get請求用來從服務器上得到資源,而post是用來向服務器提交數據;

②get將表單中數據按照name=value的形式,添加到action 所指向的URL 後面,而且二者使用"?"鏈接,而各個變量之間使用"&"鏈接;post是將表單中的數據放在HTTP協議的請求頭或消息體中,傳遞到action所指向URL;

③get傳輸的數據要受到URL長度限制(1024字節即256個字符);而post能夠傳輸大量的數據,上傳文件一般要使用post方式;

④使用get時參數會顯示在地址欄上,若是這些數據不是敏感數據,那麼可使用get;對於敏感數據仍是應用使用post;

⑤get使用MIME類型application/x-www-form-urlencoded的URL編碼(也叫百分號編碼)文本的格式傳遞參數,保證被傳送的參數由遵循規範的文本組成,例如一個空格的編碼是"%20"。

補充:GET方式提交表單的典型應用是搜索引擎。GET方式就是被設計爲查詢用的。

什麼狀況下調用doGet()和doPost()?

Form標籤裏的method的屬性爲get時調用doGet(),爲post時調用doPost()。

轉發(Forward)和重定向(Redirect)的區別?

轉發是服務器行爲,重定向是客戶端行爲。

轉發(Forword)
經過RequestDispatcher對象的forward(HttpServletRequest request,HttpServletResponse response)方法實現的。RequestDispatcher能夠經過HttpServletRequest 的getRequestDispatcher()方法得到。例以下面的代碼就是跳轉到login_success.jsp頁面。

request.getRequestDispatcher("login_success.jsp").forward(request, response);
 

重定向(Redirect) 是利用服務器返回的狀態嗎來實現的。客戶端瀏覽器請求服務器的時候,服務器會返回一個狀態碼。服務器經過HttpServletRequestResponse的setStatus(int status)方法設置狀態碼。若是服務器返回301或者302,則瀏覽器會到新的網址從新請求該資源。

  1. 從地址欄顯示來講

forward是服務器請求資源,服務器直接訪問目標地址的URL,把那個URL的響應內容讀取過來,而後把這些內容再發給瀏覽器.瀏覽器根本不知道服務器發送的內容從哪裏來的,因此它的地址欄仍是原來的地址.
redirect是服務端根據邏輯,發送一個狀態碼,告訴瀏覽器從新去請求那個地址.因此地址欄顯示的是新的URL.

  1. 從數據共享來講

forward:轉發頁面和轉發到的頁面能夠共享request裏面的數據.
redirect:不能共享數據.

  1. 從運用地方來講

forward:通常用於用戶登錄的時候,根據角色轉發到相應的模塊.
redirect:通常用於用戶註銷登錄時返回主頁面和跳轉到其它的網站等

  1. 從效率來講

forward:高.
redirect:低.

自動刷新(Refresh)

自動刷新不只能夠實現一段時間以後自動跳轉到另外一個頁面,還能夠實現一段時間以後自動刷新本頁面。Servlet中經過HttpServletResponse對象設置Header屬性實現自動刷新例如:

Response.setHeader("Refresh","1000;URL=http://localhost:8080/servlet/example.htm");
 

其中1000爲時間,單位爲毫秒。URL指定就是要跳轉的頁面(若是設置本身的路徑,就會實現沒過一秒自動刷新本頁面一次)

Servlet與線程安全

Servlet不是線程安全的,多線程併發的讀寫會致使數據不一樣步的問題。 解決的辦法是儘可能不要定義name屬性,而是要把name變量分別定義在doGet()和doPost()方法內。雖然使用synchronized(name){}語句塊能夠解決問題,可是會形成線程的等待,不是很科學的辦法。
注意:多線程的併發的讀寫Servlet類屬性會致使數據不一樣步。可是若是隻是併發地讀取屬性而不寫入,則不存在數據不一樣步的問題。所以Servlet裏的只讀屬性最好定義爲final類型的。

參考:《javaweb整合開發王者歸來》P92

JSP和Servlet是什麼關係?

其實這個問題在上面已經闡述過了,Servlet是一個特殊的Java程序,它運行於服務器的JVM中,可以依靠服務器的支持向瀏覽器提供顯示內容。JSP本質上是Servlet的一種簡易形式,JSP會被服務器處理成一個相似於Servlet的Java程序,能夠簡化頁面內容的生成。Servlet和JSP最主要的不一樣點在於,Servlet的應用邏輯是在Java文件中,而且徹底從表示層中的HTML分離開來。而JSP的狀況是Java和HTML能夠組合成一個擴展名爲.jsp的文件。有人說,Servlet就是在Java中寫HTML,而JSP就是在HTML中寫Java代碼,固然這個說法是很片面且不夠準確的。JSP側重於視圖,Servlet更側重於控制邏輯,在MVC架構模式中,JSP適合充當視圖(view)而Servlet適合充當控制器(controller)。

JSP工做原理:

JSP是一種Servlet,可是與HttpServlet的工做方式不太同樣。HttpServlet是先由源代碼編譯爲class文件後部署到服務器下,爲先編譯後部署。而JSP則是先部署後編譯。JSP會在客戶端第一次請求JSP文件時被編譯爲HttpJspPage類(接口Servlet的一個子類)。該類會被服務器臨時存放在服務器工做目錄裏面。下面經過實例給你們介紹。
工程JspLoginDemo下有一個名爲login.jsp的Jsp文件,把工程第一次部署到服務器上後訪問這個Jsp文件,咱們發現這個目錄下多了下圖這兩個東東。
.class文件即是JSP對應的Servlet。編譯完畢後再運行class文件來響應客戶端請求。之後客戶端訪問login.jsp的時候,Tomcat將再也不從新編譯JSP文件,而是直接調用class文件來響應客戶端請求。
JSP工做原理
因爲JSP只會在客戶端第一次請求的時候被編譯 ,所以第一次請求JSP時會感受比較慢,以後就會感受快不少。若是把服務器保存的class文件刪除,服務器也會從新編譯JSP。

開發Web程序時常常須要修改JSP。Tomcat可以自動檢測到JSP程序的改動。若是檢測到JSP源代碼發生了改動。Tomcat會在下次客戶端請求JSP時從新編譯JSP,而不須要重啓Tomcat。這種自動檢測功能是默認開啓的,檢測改動會消耗少許的時間,在部署Web應用的時候能夠在web.xml中將它關掉。

參考:《javaweb整合開發王者歸來》P97

JSP有哪些內置對象?做用分別是什麼?

JSP內置對象 - CSDN博客

JSP有9個內置對象:

  • request:封裝客戶端的請求,其中包含來自GET或POST請求的參數;
  • response:封裝服務器對客戶端的響應;
  • pageContext:經過該對象能夠獲取其餘對象;
  • session:封裝用戶會話的對象;
  • application:封裝服務器運行環境的對象;
  • out:輸出服務器響應的輸出流對象;
  • config:Web應用的配置對象;
  • page:JSP頁面自己(至關於Java程序中的this);
  • exception:封裝頁面拋出異常的對象。

Request對象的主要方法有哪些?

  • setAttribute(String name,Object):設置名字爲name的request 的參數值
  • getAttribute(String name):返回由name指定的屬性值
  • getAttributeNames():返回request 對象全部屬性的名字集合,結果是一個枚舉的實例
  • getCookies():返回客戶端的全部 Cookie 對象,結果是一個Cookie 數組
  • getCharacterEncoding() :返回請求中的字符編碼方式 = getContentLength() :返回請求的 Body的長度
  • getHeader(String name) :得到HTTP協議定義的文件頭信息
  • getHeaders(String name) :返回指定名字的request Header 的全部值,結果是一個枚舉的實例
  • getHeaderNames() :返回因此request Header 的名字,結果是一個枚舉的實例
  • getInputStream() :返回請求的輸入流,用於得到請求中的數據
  • getMethod() :得到客戶端向服務器端傳送數據的方法
  • getParameter(String name) :得到客戶端傳送給服務器端的有 name指定的參數值
  • getParameterNames() :得到客戶端傳送給服務器端的全部參數的名字,結果是一個枚舉的實例
  • getParameterValues(String name):得到有name指定的參數的全部值
  • getProtocol():獲取客戶端向服務器端傳送數據所依據的協議名稱
  • getQueryString() :得到查詢字符串
  • getRequestURI() :獲取發出請求字符串的客戶端地址
  • getRemoteAddr():獲取客戶端的 IP 地址
  • getRemoteHost() :獲取客戶端的名字
  • getSession([Boolean create]) :返回和請求相關 Session
  • getServerName() :獲取服務器的名字
  • getServletPath():獲取客戶端所請求的腳本文件的路徑
  • getServerPort():獲取服務器的端口號
  • removeAttribute(String name):刪除請求中的一個屬性

request.getAttribute()和 request.getParameter()有何區別?

從獲取方向來看:

getParameter()是獲取 POST/GET 傳遞的參數值;

getAttribute()是獲取對象容器中的數據值;

從用途來看:

getParameter用於客戶端重定向時,即點擊了連接或提交按扭時傳值用,即用於在用表單或url重定向傳值時接收數據用。

getAttribute用於服務器端重定向時,即在 sevlet 中使用了 forward 函數,或 struts 中使用了
mapping.findForward。 getAttribute 只能收到程序用 setAttribute 傳過來的值。

另外,能夠用 setAttribute,getAttribute 發送接收對象.而 getParameter 顯然只能傳字符串。
setAttribute 是應用服務器把這個對象放在該頁面所對應的一塊內存中去,當你的頁面服務器重定向到另外一個頁面時,應用服務器會把這塊內存拷貝另外一個頁面所對應的內存中。這樣getAttribute就能取得你所設下的值,固然這種方法能夠傳對象。session也同樣,只是對象在內存中的生命週期不同而已。getParameter只是應用服務器在分析你送上來的 request頁面的文本時,取得你設在表單或 url 重定向時的值。

總結:

getParameter 返回的是String,用於讀取提交的表單中的值;(獲取以後會根據實際須要轉換爲本身須要的相應類型,好比整型,日期類型啊等等)

getAttribute 返回的是Object,需進行轉換,可用setAttribute 設置成任意對象,使用很靈活,可隨時用

include指令include的行爲的區別

include指令: JSP能夠經過include指令來包含其餘文件。被包含的文件能夠是JSP文件、HTML文件或文本文件。包含的文件就好像是該JSP文件的一部分,會被同時編譯執行。 語法格式以下:
<%@ include file="文件相對 url 地址" %>

include動做: 動做元素用來包含靜態和動態的文件。該動做把指定文件插入正在生成的頁面。語法格式以下:

JSP九大內置對象,七大動做,三大指令-

JSP九大內置對象,七大動做,三大指令總結

講解JSP中的四種做用域

JSP中的四種做用域包括page、request、session和application,具體來講:

  • page表明與一個頁面相關的對象和屬性。
  • request表明與Web客戶機發出的一個請求相關的對象和屬性。一個請求可能跨越多個頁面,涉及多個Web組件;須要在頁面顯示的臨時數據能夠置於此做用域。
  • session表明與某個用戶與服務器創建的一次會話相關的對象和屬性。跟某個用戶相關的數據應該放在用戶本身的session中。
  • application表明與整個Web應用程序相關的對象和屬性,它實質上是跨越整個Web應用程序,包括多個頁面、請求和會話的一個全局做用域。

如何實現JSP或Servlet的單線程模式?

對於JSP頁面,能夠經過page指令進行設置。
<%@page isThreadSafe=」false」%>

對於Servlet,可讓自定義的Servlet實現SingleThreadModel標識接口。

說明:若是將JSP或Servlet設置成單線程工做模式,會致使每一個請求建立一個Servlet實例,這種實踐將致使嚴重的性能問題(服務器的內存壓力很大,還會致使頻繁的垃圾回收),因此一般狀況下並不會這麼作。

實現會話跟蹤的技術有哪些?

  1. 使用Cookie

向客戶端發送Cookie

  1.  
    Cookie c = new Cookie( "name", "value"); //建立Cookie
  2.  
    c.setMaxAge( 60* 60* 24); //設置最大時效,此處設置的最大時效爲一天
  3.  
    response.addCookie(c); //把Cookie放入到HTTP響應中

從客戶端讀取Cookie

  1.  
    String name = "name";
  2.  
    Cookie[]cookies =request.getCookies();
  3.  
    if(cookies != null){
  4.  
    for( int i= 0;i<cookies.length;i++){
  5.  
    Cookie cookie =cookies[i];
  6.  
    if(name.equals(cookis.getName()))
  7.  
    //something is here.
  8.  
    //you can get the value
  9.  
    cookie.getValue();
  10.  
     
  11.  
    }
  12.  
    }

優勢: 數據能夠持久保存,不須要服務器資源,簡單,基於文本的Key-Value

缺點: 大小受到限制,用戶能夠禁用Cookie功能,因爲保存在本地,有必定的安全風險。

  1. URL 重寫

在URL中添加用戶會話的信息做爲請求的參數,或者將惟一的會話ID添加到URL結尾以標識一個會話。

優勢: 在Cookie被禁用的時候依然可使用

缺點: 必須對網站的URL進行編碼,全部頁面必須動態生成,不能用預先記錄下來的URL進行訪問。

3.隱藏的表單域

<input type="hidden" name ="session" value="..."/>
 

優勢: Cookie被禁時可使用

缺點: 全部頁面必須是表單提交以後的結果。

  1. HttpSession

在全部會話跟蹤技術中,HttpSession對象是最強大也是功能最多的。當一個用戶第一次訪問某個網站時會自動建立 HttpSession,每一個用戶能夠訪問他本身的HttpSession。能夠經過HttpServletRequest對象的getSession方 法得到HttpSession,經過HttpSession的setAttribute方法能夠將一個值放在HttpSession中,經過調用 HttpSession對象的getAttribute方法,同時傳入屬性名就能夠獲取保存在HttpSession中的對象。與上面三種方式不一樣的 是,HttpSession放在服務器的內存中,所以不要將過大的對象放在裏面,即便目前的Servlet容器能夠在內存將滿時將HttpSession 中的對象移到其餘存儲設備中,可是這樣勢必影響性能。添加到HttpSession中的值能夠是任意Java對象,這個對象最好實現了 Serializable接口,這樣Servlet容器在必要的時候能夠將其序列化到文件中,不然在序列化時就會出現異常。

Cookie和Session的的區別?

  1. 因爲HTTP協議是無狀態的協議,因此服務端須要記錄用戶的狀態時,就須要用某種機制來識具體的用戶,這個機制就是Session.典型的場景好比購物車,當你點擊下單按鈕時,因爲HTTP協議無狀態,因此並不知道是哪一個用戶操做的,因此服務端要爲特定的用戶建立了特定的Session,用用於標識這個用戶,而且跟蹤用戶,這樣才知道購物車裏面有幾本書。這個Session是保存在服務端的,有一個惟一標識。在服務端保存Session的方法不少,內存、數據庫、文件都有。集羣的時候也要考慮Session的轉移,在大型的網站,通常會有專門的Session服務器集羣,用來保存用戶會話,這個時候 Session 信息都是放在內存的,使用一些緩存服務好比Memcached之類的來放 Session。
  2. 思考一下服務端如何識別特定的客戶?這個時候Cookie就登場了。每次HTTP請求的時候,客戶端都會發送相應的Cookie信息到服務端。實際上大多數的應用都是用 Cookie 來實現Session跟蹤的,第一次建立Session的時候,服務端會在HTTP協議中告訴客戶端,須要在 Cookie 裏面記錄一個Session ID,之後每次請求把這個會話ID發送到服務器,我就知道你是誰了。有人問,若是客戶端的瀏覽器禁用了 Cookie 怎麼辦?通常這種狀況下,會使用一種叫作URL重寫的技術來進行會話跟蹤,即每次HTTP交互,URL後面都會被附加上一個諸如 sid=xxxxx 這樣的參數,服務端據此來識別用戶。
  3. Cookie其實還能夠用在一些方便用戶的場景下,設想你某次登錄過一個網站,下次登陸的時候不想再次輸入帳號了,怎麼辦?這個信息能夠寫到Cookie裏面,訪問網站的時候,網站頁面的腳本能夠讀取這個信息,就自動幫你把用戶名給填了,可以方便一下用戶。這也是Cookie名稱的由來,給用戶的一點甜頭。因此,總結一下:Session是在服務端保存的一個數據結構,用來跟蹤用戶的狀態,這個數據能夠保存在集羣、數據庫、文件中;Cookie是客戶端保存用戶信息的一種機制,用來記錄用戶的一些信息,也是實現Session的一種方式。

Java集合篇常見問題

List,Set,Map三者的區別及總結

  • List:對付順序的好幫手

    List接口存儲一組不惟一(能夠有多個元素引用相同的對象),有序的對象
  • Set:注重獨一無二的性質

    不容許重複的集合。不會有多個元素引用相同的對象。

  • Map:用Key來搜索的專家

    使用鍵值對存儲。Map會維護與Key有關聯的值。兩個Key能夠引用相同的對象,但Key不能重複,典型的Key是String類型,但也能夠是任何對象。

Arraylist 與 LinkedList 區別

Arraylist底層使用的是數組(存讀數據效率高,插入刪除特定位置效率低),LinkedList底層使用的是雙向循環鏈表數據結構(插入,刪除效率特別高)。學過數據結構這門課後咱們就知道採用鏈表存儲,插入,刪除元素時間複雜度不受元素位置的影響,都是近似O(1)而數組爲近似O(n),所以當數據特別多,並且常常須要插入刪除元素時建議選用LinkedList.通常程序只用Arraylist就夠用了,由於通常數據量都不會蠻大,Arraylist是使用最多的集合類。

ArrayList 與 Vector 區別(爲何要用Arraylist取代Vector呢?)

Vector類的全部方法都是同步的。能夠由兩個線程安全地訪問一個Vector對象、可是一個線程訪問Vector
,代碼要在同步操做上耗費大量的時間。Arraylist不是同步的,因此在不須要同步時建議使用Arraylist。

HashMap 和 Hashtable 的區別

  1. HashMap是非線程安全的,HashTable是線程安全的;HashTable內部的方法基本都通過synchronized修飾。

  2. 由於線程安全的問題,HashMap要比HashTable效率高一點,HashTable基本被淘汰。
  3. HashMap容許有null值的存在,而在HashTable中put進的鍵值只要有一個null,直接拋出NullPointerException。

Hashtable和HashMap有幾個主要的不一樣:線程安全以及速度。僅在你須要徹底的線程安全的時候使用Hashtable,而若是你使用Java5或以上的話,請使用ConcurrentHashMap吧

HashSet 和 HashMap 區別

HashSet 和 HashMap 區別

HashMap 和 ConcurrentHashMap 的區別

HashMap與ConcurrentHashMap的區別

  1. ConcurrentHashMap對整個桶數組進行了分割分段(Segment),而後在每個分段上都用lock鎖進行保護,相對於HashTable的synchronized鎖的粒度更精細了一些,併發性能更好,而HashMap沒有鎖機制,不是線程安全的。(JDK1.8以後ConcurrentHashMap啓用了一種全新的方式實現,利用CAS算法。)
  2. HashMap的鍵值對容許有null,可是ConCurrentHashMap都不容許。

HashSet如何檢查重複

當你把對象加入HashSet時,HashSet會先計算對象的hashcode值來判斷對象加入的位置,同時也會與其餘加入的對象的hashcode值做比較,若是沒有相符的hashcode,HashSet會假設對象沒有重複出現。可是若是發現有相同hashcode值的對象,這時會調用equals()方法來檢查hashcode相等的對象是否真的相同。若是二者相同,HashSet就不會讓加入操做成功。(摘自個人Java啓蒙書《Head fist java》第二版)

hashCode()與equals()的相關規定:

  1. 若是兩個對象相等,則hashcode必定也是相同的
  2. 兩個對象相等,對兩個equals方法返回true
  3. 兩個對象有相同的hashcode值,它們也不必定是相等的
  4. 綜上,equals方法被覆蓋過,則hashCode方法也必須被覆蓋
  5. hashCode()的默認行爲是對堆上的對象產生獨特值。若是沒有重寫hashCode(),則該class的兩個對象不管如何都不會相等(即便這兩個對象指向相同的數據)。

==與equals的區別

  1. ==是判斷兩個變量或實例是否是指向同一個內存空間 equals是判斷兩個變量或實例所指向的內存空間的值是否是相同
  2. ==是指對內存地址進行比較 equals()是對字符串的內容進行比較3.==指引用是否相同 equals()指的是值是否相同

comparable 和 comparator的區別?

  • comparable接口其實是出自java.lang包 它有一個 compareTo(Object obj)方法用來排序
  • comparator接口其實是出自 java.util 包它有一個compare(Object obj1, Object obj2)方法用來排序

通常咱們須要對一個集合使用自定義排序時,咱們就要重寫compareTo方法或compare方法,當咱們須要對某一個集合實現兩種排序方式,好比一個song對象中的歌名和歌手名分別採用一種排序方法的話,咱們能夠重寫compareTo方法和使用自制的Comparator方法或者以兩個Comparator來實現歌名排序和歌星名排序,第二種表明咱們只能使用兩個參數版的Collections.sort().

Comparator定製排序

  1.  
    import java.util.ArrayList;
  2.  
    import java.util.Collections;
  3.  
    import java.util.Comparator;
  4.  
     
  5.  
    public class CollectionsSort {
  6.  
     
  7.  
    public static void main(String[] args) {
  8.  
     
  9.  
    ArrayList<Integer> arrayList = new ArrayList<Integer>();
  10.  
    arrayList.add(- 1);
  11.  
    arrayList.add( 3);
  12.  
    arrayList.add( 3);
  13.  
    arrayList.add(- 5);
  14.  
    arrayList.add( 7);
  15.  
    arrayList.add( 4);
  16.  
    arrayList.add(- 9);
  17.  
    arrayList.add(- 7);
  18.  
    System.out.println( "原始數組:");
  19.  
    System.out.println(arrayList);
  20.  
    // void reverse(List list):反轉
  21.  
    Collections.reverse(arrayList);
  22.  
    System.out.println( "Collections.reverse(arrayList):");
  23.  
    System.out.println(arrayList);
  24.  
    /*
  25.  
    * void rotate(List list, int distance),旋轉。
  26.  
    * 當distance爲正數時,將list後distance個元素總體移到前面。當distance爲負數時,將
  27.  
    * list的前distance個元素總體移到後面。
  28.  
     
  29.  
    Collections.rotate(arrayList, 4);
  30.  
    System.out.println("Collections.rotate(arrayList, 4):");
  31.  
    System.out.println(arrayList);*/
  32.  
     
  33.  
    // void sort(List list),按天然排序的升序排序
  34.  
    Collections.sort(arrayList);
  35.  
    System.out.println( "Collections.sort(arrayList):");
  36.  
    System.out.println(arrayList);
  37.  
     
  38.  
    // void shuffle(List list),隨機排序
  39.  
    Collections.shuffle(arrayList);
  40.  
    System.out.println( "Collections.shuffle(arrayList):");
  41.  
    System.out.println(arrayList);
  42.  
     
  43.  
    // 定製排序的用法
  44.  
    Collections.sort(arrayList, new Comparator<Integer>() {
  45.  
     
  46.  
    @Override
  47.  
    public int compare(Integer o1, Integer o2) {
  48.  
    return o2.compareTo(o1);
  49.  
    }
  50.  
    });
  51.  
    System.out.println( "定製排序後:");
  52.  
    System.out.println(arrayList);
  53.  
    }
  54.  
     
  55.  
    }

重寫compareTo方法實現按年齡來排序

  1.  
    package map;
  2.  
     
  3.  
    import java.util.Set;
  4.  
    import java.util.TreeMap;
  5.  
     
  6.  
    public class TreeMap2 {
  7.  
     
  8.  
    public static void main(String[] args) {
  9.  
    // TODO Auto-generated method stub
  10.  
    TreeMap<Person, String> pdata = new TreeMap<Person, String>();
  11.  
    pdata.put( new Person( "張三", 30), "zhangsan");
  12.  
    pdata.put( new Person( "李四", 20), "lisi");
  13.  
    pdata.put( new Person( "王五", 10), "wangwu");
  14.  
    pdata.put( new Person( "小紅", 5), "xiaohong");
  15.  
    // 獲得key的值的同時獲得key所對應的值
  16.  
    Set<Person> keys = pdata.keySet();
  17.  
    for (Person key : keys) {
  18.  
    System.out.println(key.getAge() + "-" + key.getName());
  19.  
     
  20.  
    }
  21.  
    }
  22.  
    }
  23.  
     
  24.  
    // person對象沒有實現Comparable接口,因此必須實現,這樣纔不會出錯,纔可使treemap中的數據按順序排列
  25.  
    // 前面一個例子的String類已經默認實現了Comparable接口,詳細能夠查看String類的API文檔,另外其餘
  26.  
    // 像Integer類等都已經實現了Comparable接口,因此不須要另外實現了
  27.  
     
  28.  
    class Person implements Comparable<Person> {
  29.  
    private String name;
  30.  
    private int age;
  31.  
     
  32.  
    public Person(String name, int age) {
  33.  
    super();
  34.  
    this.name = name;
  35.  
    this.age = age;
  36.  
    }
  37.  
     
  38.  
    public String getName() {
  39.  
    return name;
  40.  
    }
  41.  
     
  42.  
    public void setName(String name) {
  43.  
    this.name = name;
  44.  
    }
  45.  
     
  46.  
    public int getAge() {
  47.  
    return age;
  48.  
    }
  49.  
     
  50.  
    public void setAge(int age) {
  51.  
    this.age = age;
  52.  
    }
  53.  
     
  54.  
    /**
  55.  
    * TODO重寫compareTo方法實現按年齡來排序
  56.  
    */
  57.  
    @Override
  58.  
    public int compareTo(Person o) {
  59.  
    // TODO Auto-generated method stub
  60.  
    if ( this.age > o.getAge()) {
  61.  
    return 1;
  62.  
    } else if ( this.age < o.getAge()) {
  63.  
    return - 1;
  64.  
    }
  65.  
    return age;
  66.  
    }
  67.  
    }

如何對Object的list排序?

  • 對objects數組進行排序,咱們能夠用Arrays.sort()方法
  • 對objects的集合進行排序,須要使用Collections.sort()方法

如何實現數組與List的相互轉換?

List轉數組:toArray(arraylist.size()方法;數組轉List:Arrays的asList(a)方法

  1.  
    List<String> arrayList = new ArrayList<String>();
  2.  
    arrayList.add( "s");
  3.  
    arrayList.add( "e");
  4.  
    arrayList.add( "n");
  5.  
    /**
  6.  
    * ArrayList轉數組
  7.  
    */
  8.  
    int size=arrayList.size();
  9.  
    String[] a = arrayList.toArray( new String[size]);
  10.  
    //輸出第二個元素
  11.  
    System.out.println(a[ 1]); //結果:e
  12.  
    //輸出整個數組
  13.  
    System.out.println(Arrays.toString(a)); //結果:[s, e, n]
  14.  
    /**
  15.  
    * 數組轉list
  16.  
    */
  17.  
    List<String> list=Arrays.asList(a);
  18.  
    /**
  19.  
    * list轉Arraylist
  20.  
    */
  21.  
    List<String> arrayList2 = new ArrayList<String>();
  22.  
    arrayList2.addAll(list);
  23.  
    System.out.println(list);

如何求ArrayList集合的交集 並集 差集 去重複並集

須要用到List接口中定義的幾個方法:

  • addAll(Collection<? extends E> c) :按指定集合的Iterator返回的順序將指定集合中的全部元素追加到此列表的末尾
    實例代碼:
  • retainAll(Collection<?> c): 僅保留此列表中包含在指定集合中的元素。
  • removeAll(Collection<?> c) :今後列表中刪除指定集合中包含的全部元素。
  1.  
    package list;
  2.  
     
  3.  
    import java.util.ArrayList;
  4.  
    import java.util.List;
  5.  
     
  6.  
    public class MethodDemo {
  7.  
     
  8.  
    public static void main(String[] args) {
  9.  
    // TODO Auto-generated method stub
  10.  
    List<Integer> list1 = new ArrayList<Integer>();
  11.  
    list1.add( 1);
  12.  
    list1.add( 2);
  13.  
    list1.add( 3);
  14.  
    list1.add( 4);
  15.  
     
  16.  
    List<Integer> list2 = new ArrayList<Integer>();
  17.  
    list2.add( 2);
  18.  
    list2.add( 3);
  19.  
    list2.add( 4);
  20.  
    list2.add( 5);
  21.  
    // 並集
  22.  
    // list1.addAll(list2);
  23.  
    // 交集
  24.  
    //list1.retainAll(list2);
  25.  
    // 差集
  26.  
    // list1.removeAll(list2);
  27.  
    // 無重複並集
  28.  
    list2.removeAll(list1);
  29.  
    list1.addAll(list2);
  30.  
    for (Integer i : list1) {
  31.  
    System.out.println(i);
  32.  
    }
  33.  
    }
  34.  
     
  35.  
    }

HashMap 的工做原理及代碼實現

集合框架源碼學習之HashMap(JDK1.8)

ConcurrentHashMap 的工做原理及代碼實現

ConcurrentHashMap實現原理及源碼分析

相關文章
相關標籤/搜索