Java面試常見知識點總結(一)

Java面試常見知識點總結(一)

1.sleep()和wait():

  Java中的多線程是一種搶佔式的機制,而不是分時機制。搶佔式的機制是有多個線程處於可運行狀態,可是隻有一個線程在運行。
  ● 共同點
   (1) 他們都是在多線程的環境下,均可以在程序的調用處阻塞指定的毫秒數,並返回。
   (2) wait()和sleep()均可以經過interrupt()方法 打斷線程的暫停狀態 ,從而使線程馬上拋出InterruptedException。
       若是線程A但願當即結束線程B,則能夠對線程B對應的Thread實例調用interrupt方法。若是此刻線程B正在wait/sleep/join,則線程B會馬上拋出InterruptedException,在catch() {} 中直接return便可安全地結束線程。
      須要注意的是,InterruptedException是線程本身從內部拋出的,並非interrupt()方法拋出的。對某一線程調用 interrupt()時,若是該線程正在執行普通的代碼,那麼該線程根本就不會拋出InterruptedException。可是,一旦該線程進入到 wait()/sleep()/join()後,就會馬上拋出InterruptedException 。
   ● 不一樣點
   (1) 每一個對象都有一個鎖來控制同步訪問。Synchronized關鍵字能夠和對象的鎖交互,來實現線程的同步。
      sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其餘線程可使用同步控制塊或者方法。
   (2) wait,notify和notifyAll只能在同步控制方法或者同步控制塊裏面使用,而sleep能夠在任何地方使用
   (3) sleep必須捕獲異常,而wait,notify和notifyAll不須要捕獲異常
   (4) sleep是線程類(Thread)的方法,致使此線程暫停執行指定時間,給執行機會給其餘線程,可是監控狀態依然保持,到時後會自動恢復。調用sleep不會釋放對象鎖。
   (5) wait是Object類的方法,對此對象調用wait方法致使本線程放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象發出notify方法(或notifyAll)後本線程才進入對象鎖定池準備得到對象鎖進入運行狀態。html

2.截止JDK1.8版本,java併發框架支持鎖包括:

  1) 自旋鎖, 自旋,jvm默認是10次吧,有jvm本身控制。for去爭取鎖.
  2) 阻塞鎖 被阻塞的線程,不會爭奪鎖.
  3) 可重入鎖 屢次進入改鎖的域.
  4) 讀寫鎖.
  5) 互斥鎖 鎖自己就是互斥的.
  6) 悲觀鎖 不相信,這裏會是安全的,必須所有上鎖.
  7) 樂觀鎖 相信,這裏是安全的.
  8) 公平鎖 有優先級的鎖.
  9) 非公平鎖 無優先級的鎖.
  10) 偏向鎖 無競爭不鎖,有競爭掛起,轉爲輕量鎖.
  11) 對象鎖 鎖住對象.
  12) 線程鎖.
  13) 鎖粗化 多鎖變成一個,本身處理.
  14) 輕量級鎖 CAS實現.
  15) 鎖消除 偏向鎖就是鎖消除的一種.
  16) 鎖膨脹 jvm實現,鎖粗化.
  17) 信號量 使用阻塞鎖 實現的一種策略.
  18) 排它鎖:X鎖,若事務T對數據對象A加上X鎖,則只容許T讀取和修改A,其餘任何事務都不能再對A加任何類型的鎖,直到T釋放A上的鎖。這就保證了其餘事務在T釋放A上的鎖以前不能再讀取和修改A。java

3.結構型模式:

   結構型模式是描述如何將類對象結合在一塊兒,造成一個更大的結構,結構模式描述兩種不一樣的東西:類與類的實例。故能夠分爲類結構模式和對象結構模式。
   在GoF設計模式中,結構型模式有:
  1) 適配器模式 Adapter
  適配器模式是將一個類的接口轉換成客戶但願的另一個接口。適配器模式使得本來因爲接口不兼容而不能一塊兒工做的那些類能夠一塊兒工做。
  兩個成熟的類須要通訊,可是接口不一樣,因爲開閉原則,咱們不能去修改這兩個類的接口,因此就須要一個適配器來完成銜接過程。
  2) 橋接模式 Bridge
  橋接模式將抽象部分與它的實現部分分離,是它們均可以獨立地變化。它很好的支持了開閉原則和組合鋸和複用原則。實現系統可能有多角度分類,每一種分類都有可能變化,那麼就把這些多角度分離出來讓他們獨立變化,減小他們之間的耦合。
  3) 組合模式 Composite
  組合模式將對象組合成樹形結構以表示部分-總體的層次結構,組合模式使得用戶對單個對象和組合對象的使用具備一致性。
  4) 裝飾模式 Decorator
   裝飾模式動態地給一個對象添加一些額外的職責,就增長功能來講,它比生成子類更靈活。也能夠這樣說,裝飾模式把複雜類中的核心職責和裝飾功能區分開了,這樣既簡化了複雜類,有去除了相關類中重複的裝飾邏輯。 裝飾模式沒有經過繼承原有類來擴展功能,但卻達到了同樣的目的,並且比繼承更加靈活,因此能夠說裝飾模式是繼承關係的一種替代方案
  5) 外觀模式 Facade
  外觀模式爲子系統中的一組接口提供了贊成的界面,外觀模式定義了一個高層接口,這個接口使得這一子系統更加容易使用。
  外觀模式中,客戶對各個具體的子系統是不瞭解的,因此對這些子系統進行了封裝,對外只提供了用戶所明白的單一而簡單的接口,用戶直接使用這個接口就能夠完成操做,而不用去理睬具體的過程,並且子系統的變化不會影響到用戶,這樣就作到了信息隱蔽。
  6) 享元模式 Flyweight
  享元模式爲運用共享技術有效的支持大量細粒度的對象。由於它能夠經過共享大幅度地減小單個實例的數目,避免了大量很是類似類的開銷。
  享元模式是一個類別的多個對象共享這個類別的一個對象,而不是各自再實例化各自的對象。這樣就達到了節省內存的目的。
  7) 代理模式 Proxy
  爲其餘對象提供一種代理,並由代理對象控制對原對象的引用,以間接控制對原對象的訪問。面試

4.Statement、PreparedStatement和CallableStatement的異同:  

    1) Statement繼承自Wrapper、PreparedStatement繼承自Statement、CallableStatement繼承自PreparedStatement算法

    2) Statement接口提供了執行語句和獲取結果的基本方法;
        PreparedStatement接口添加了處理 IN 參數的方法;
        CallableStatement接口添加了處理 OUT 參數的方法。
    3) a.Statement: 普通的不帶參的查詢SQL; 支持批量更新, 批量刪除;
        b.PreparedStatement: 可變參數的SQL, 編譯一次, 執行屢次, 效率高;
           安全性好,有效防止Sql注入等問題;
           支持批量更新, 批量刪除;
        c.CallableStatement: 繼承自PreparedStatement, 支持帶參數的SQL操做;
           支持調用存儲過程, 提供了對輸出和輸入/輸出參數(INOUT)的支持;
         Statement每次執行sql語句,數據庫都要執行sql語句的編譯, 最好用於僅執行一次查詢並返回結果的情形,效率高於PreparedStatement。
    4) PreparedStatement預編譯的,使用PreparedStatement有幾個好處:: sql

      (1) 在執行可變參數的一條SQL時,PreparedStatement比Statement的效率高,由於DBMS預編譯一條SQL固然會比屢次編譯一條SQL的效率要高。
      (2) 安全性好,有效防止Sql注入等問題。
      (3) 對於屢次重複執行的語句,使用PreparedStament效率會更高一點,而且在這種狀況下也比較適合使用batch;
      (4) 代碼的可讀性和可維護性。數據庫

5.對於JVM內存配置參數:

-Xmx10240m -Xms10240m -Xmn5120m -XXSurvivorRatio=3

   其最小內存值和Survivor區總大小分別是(10240m,2048m).設計模式

   -Xmx:最大堆大小.
   -Xms:初始堆大小.
   -Xmn : 年輕代大小.
   -XXSurvivorRatio:年輕代中Eden區與Survivor區的大小比值.
   -Xms初始堆大小即最小內存值, 爲10240m.
    XXSurvivorRatio=3,即Eden:FromSurvivor:ToSurvivor=3:1:1;因此Survivor一共是2048m.緩存

 6.類加載過程:

     類從被加載到虛擬機內存中開始,到卸載出內存爲止,它的整個生命週期包括:加載(Loading)、驗證(Verification)、準備(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸載(Unloading)7個階段。其中準備、驗證、解析3個部分統稱爲鏈接(Linking)。如圖所示:安全

     

    這裏寫圖片描述:網絡

    加載、驗證、準備、初始化和卸載這5個階段的順序是肯定的,類的加載過程必須按照這種順序循序漸進地開始,而解析階段則不必定:它在某些狀況下能夠在初始化階段以後再開始,這是爲了支持Java語言的運行時綁定(也稱爲動態綁定或晚期綁定)。如下陳述的內容都已HotSpot爲基準。

    ● 加載

    在加載階段(能夠參考java.lang.ClassLoader的loadClass()方法),虛擬機須要完成如下3件事情:

   1) 經過一個類的全限定名來獲取定義此類的二進制字節流(並無指明要從一個Class文件中獲取,能夠從其餘渠道,譬如:網絡、動態生成、數據庫等);
   2) 將這個字節流所表明的靜態存儲結構轉化爲方法區的運行時數據結構;
   3) 在內存中生成一個表明這個類的java.lang.Class對象,做爲方法區這個類的各類數據的訪問入口;
   加載階段和鏈接階段(Linking)的部份內容(如一部分字節碼文件格式驗證動做)是交叉進行的,加載階段還沒有完成,鏈接階段可能已經開始,但這些夾在加載階段之中進行的動做,仍然屬於鏈接階段的內容,這兩個階段的開始時間仍然保持着固定的前後順序。

    ● 驗證

    驗證是鏈接階段的第一步,這一階段的目的是爲了確保Class文件的字節流中包含的信息符合當前虛擬機的要求,而且不會危害虛擬機自身的安全。
    驗證階段大體會完成4個階段的檢驗動做:

     1) 文件格式驗證:驗證字節流是否符合Class文件格式的規範;例如:是否以魔術0xCAFEBABE開頭、主次版本號是否在當前虛擬機的處理範圍以內、常量池中的常量是否有不被支持的類型。
     2) 元數據驗證:對字節碼描述的信息進行語義分析(注意:對比javac編譯階段的語義分析),以保證其描述的信息符合Java語言規範的要求;例如:這個類是否有父類,除了java.lang.Object以外。
     3) 字節碼驗證:經過數據流和控制流分析,肯定程序語義是合法的、符合邏輯的。
     4) 符號引用驗證:確保解析動做能正確執行。
    驗證階段是很是重要的,但不是必須的,它對程序運行期沒有影響,若是所引用的類通過反覆驗證,那麼能夠考慮採用-Xverifynone參數來關閉大部分的類驗證措施,以縮短虛擬機類加載的時間。

    ● 準備

    準備階段是正式爲類變量分配內存並設置類變量初始值的階段,這些變量所使用的內存都將在方法區中進行分配。這時候進行內存分配的僅包括類變量(被static修飾的變量),而不包括實例變量,實例變量將會在對象實例化時隨着對象一塊兒分配在堆中。其次,這裏所說的初始值「一般狀況」下是數據類型的零值,假設一個類變量的定義爲:

public static int value=123;

    那變量value在準備階段事後的初始值爲0而不是123. 由於這時候還沒有開始執行任何java方法,而把value賦值爲123的putstatic指令是程序被編譯後,存放於類構造器()方法之中,因此把value賦值爲123的動做將在初始化階段纔會執行。
    至於「特殊狀況」是指:public static final int value=123,即當類字段的字段屬性是ConstantValue時,會在準備階段初始化爲指定的值,因此標註爲final以後,value的值在準備階段初始化爲123而非0.

    ● 解析

    解析階段是虛擬機將常量池內的符號引用替換爲直接引用的過程。解析動做主要針對類或接口、字段、類方法、接口方法、方法類型、方法句柄和調用點限定符7類符號引用進行。

    ● 初始化

     類初始化階段是類加載過程的最後一步,到了初始化階段,才真正開始執行類中定義的java程序代碼。在準備極端,變量已經付過一次系統要求的初始值,而在初始化階段,則根據程序猿經過程序制定的主管計劃去初始化類變量和其餘資源,或者說:初始化階段是執行類構造器<clinit>()方法的過程.
   <clinit>()方法是由編譯器自動收集類中的全部類變量的賦值動做和靜態語句塊static{}中的語句合併產生的,編譯器收集的順序是由語句在源文件中出現的順序所決定的,靜態語句塊只能訪問到定義在靜態語句塊以前的變量,定義在它以後的變量,在前面的靜態語句塊能夠賦值,可是不能訪問。以下:

複製代碼

public class Test
{
    static
    {
        i=0;
        System.out.println(i);//這句編譯器會報錯:Cannot reference a field before it is defined(非法向前應用)
    }
    static int i=1;
}

複製代碼

    更多介紹,請移步:http://blog.csdn.net/u013256816/article/details/50829596

7.JVM內存:

     大多數 JVM 將內存區域劃分爲: Method Area(Non-Heap)(方法區),  Heap(堆),  Program Counter Register(程序計數器),  VM Stack(虛擬機棧,也有翻譯成JAVA 方法棧的), Native Method Stack ( 本地方法棧 ),其中Method AreaHeap線程共享的 ,VM StackNative Method StackProgram Counter Register非線程共享的。

     爲何分爲線程共享和非線程共享的呢?

    首先咱們熟悉一下一個通常性的 Java 程序的工做過程。一個 Java 源程序文件,會被編譯爲字節碼文件(以 class 爲擴展名),每一個java程序都須要運行在本身的JVM上,而後告知 JVM 程序的運行入口,再被 JVM 經過字節碼解釋器加載運行。

     那麼程序開始運行後,都是如何涉及到各內存區域的呢?
     歸納地說來,JVM初始運行的時候都會分配好 Method Area(方法區) 和Heap(堆) ,而JVM 每遇到一個線程,就爲其分配一個 Program Counter Register(程序計數器) , VM Stack(虛擬機棧)和Native Method Stack (本地方法棧), 當線程終止時,三者(虛擬機棧,本地方法棧和程序計數器)所佔用的內存空間也會被釋放掉。這也是爲何我把內存區域分爲線程共享和非線程共享的緣由,非線程共享的那三個區域的生命週期與所屬線程相同,而線程共享的區域與JAVA程序運行的生命週期相同,因此這也是系統垃圾回收的場所只發生在線程共享的區域(實際上對大部分虛擬機來講知發生在Heap上)的緣由。

    方法區在JVM中也是一個很是重要的區域,它與同樣,是被線程共享的區域。 在方法區中,存儲了每一個類的信息(包括類的名稱、方法信息、字段信息)、靜態變量、常量以及編譯器編譯後的代碼等。

    程序計數器是Java虛擬機中惟一一個沒有規定任何內存溢出OutOfMemoryError的內存區域,Java虛擬機中的程序計數器指向正在執行的字節碼地址,而不是下一條。

8.Java垃圾回收算法:

   兩個最基本的Java垃圾回收算法:複製算法和標記清理算法。

   複製算法:兩個區域A和B,初始對象在A,繼續存活的對象被轉移到B。此爲新生代最經常使用的算法。
   標記清理:一塊區域,標記要回收的對象,而後回收,必定會出現碎片,那麼引出:標記-整理算法:多了碎片整理,整理出更大的內存放更大的對象。
   兩個概念:新生代和年老代。
      新生代:初始對象,生命週期短的。
      永久代:長時間存在的對象。
   整個java的垃圾回收是新生代和年老代的協做,這種叫作分代回收。
   P.S:Serial New收集器是針對新生代的收集器,採用的是複製算法。
           Parallel New(並行)收集器,新生代採用複製算法,老年代採用標記整理。
           Parallel Scavenge(並行)收集器,針對新生代,採用複製收集算法。
           Serial Old(串行)收集器,新生代採用複製,老年代採用標記清理。
           Parallel Old(並行)收集器,針對老年代,標記整理。
           CMS收集器,基於標記清理。
           G1收集器:總體上是基於標記清理,局部採用複製。
   綜上:新生代基本採用複製算法,老年代採用標記整理算法。cms採用標記清理

9.重寫(Overriding)和重載(Overloading):

    重寫Overriding是父類與子類之間多態性的一種表現,重載Overloading是一個類中多態性的一種表現。

    若是在子類中定義某方法與其父類有相同的名稱和參數,咱們說該方法被重寫 (Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被「屏蔽」了。

    若是在一個類中定義了多個同名的方法,它們或有不一樣的參數個數或有不一樣的參數類型,則稱爲方法的重載(Overloading)。

    Overloaded的方法是能夠改變返回值的類型。

10.優化Hibernate所鼓勵的7大措施:

   1) 儘可能使用many-to-one,避免使用單項one-to-many;    2) 靈活使用單向one-to-many;    3) 不用一對一,使用多對一代替一對一;    4) 配置對象緩存,不使用集合緩存;    5) 一對多使用Bag 多對一使用Set;    6) 繼承使用顯示多態 HQL:from object polymorphism="exlicit" 避免查出全部對象;    7) 消除大表,使用二級緩存。

相關文章
相關標籤/搜索