Java 面試總結 面試常問的關鍵字總結
文章出處http://www.cnblogs.com/IUbanana/p/7116520.html
關鍵字:
- final finalize finally
- throws和throw
- static關鍵字的作用
- abstract 和 interface
- super 和 this
- synchronize 和 volatile
1. final finalize finally對比
(1)性質不同
- final為關鍵字;
- finalize()為方法;
- finally為為區塊標誌,用於try語句中;
(2)作用不同
- final:用於標識常量的關鍵字,final標識的關鍵字存儲在常量池中(在這裏final常量的具體用法將在下面進行介紹);final定義的變量值不可變,方法不可覆寫,類不可繼承。
- 定義變量:一旦初始化(聲明處或構造函數中)便不可改變。對基本類型是其值不可變,對引用類型是引用不可變;(String天生就是final的)
- 定義方法:1)使用final定義的方法,不允許覆寫,認為其功能滿足要求無需擴展時;2)允許編譯器將所有對此方法的調用轉化為inline(行內機制),即可以將此方法直接復制在調用處,而不是進行例行的方法調用(保存斷點、壓棧),可以提高效率。但如果過多的話,會造成代碼膨脹,反而會影響效率,慎用。
-
定義類:無法被繼承,這也就意味著此類在一個繼承樹中是一個葉子類;類成員是不是final都可以。
- finalize():方法在Object中進行了定義,用於在對象“消失”時,由JVM進行調用用於對對象進行垃圾回收,類似於C++中的析構函數;用戶自定義時,用於釋放對象占用的資源(比如進行I/0操作);
- finally{}:用於標識代碼塊,與try{}進行配合,是異常處理模型的補充,不論try中的代碼執行完或沒有執行完(這裏指有異常),該代碼塊之中的程序必定會進行;不可單獨使用,在一個try...catch...finally語句塊中最多只有一個finally;一般用來維護對象的內部狀態,清理非內存資源。
2. throws和throw對比
(1)使用位置不同
- throw位於方法體內部,可以作為單獨語句使用;
- throws位於方法頭部的參數列表後面,不能單獨使用;
(2)內容不同
- throw拋出一個具體的異常對象,而且只能是一個;
- throws聲明拋出的異常類,可以同時聲明多個;
(3)作用不同
- throw用於在程序中拋出異常,一旦執行說明一定有異常拋出,由方法體內部語句處理異常;
- throws用於聲明在該方法內可能拋出的異常類,如果拋出了異常,由該方法的調用者處理,層層上拋;
總結:函數調用時,如果需要向上層拋出異常,就必須在函數頭部顯式地聲明(throws Exception1, Exception2)異常類型;如果僅需要在方法體內部處理異常,方法體內部可自行處理該異常,thorw拋出具體的異常實例(catch(Exception1 e){...})。
3. static關鍵字的作用
static關鍵字可用來修飾屬性、方法、代碼塊,目的是把對象相關的變成類相關的,即:不加static的成員是對象相關的,歸單個對象所有;加static修飾的成員是類成員,可以通過類名直接調用,歸所有對象所有。
static修飾的成員變量和成員方法習慣上稱為靜態變量和靜態方法,可以直接通過類名來訪問,訪問語法為:
- 類名.靜態方法名(參數列表…)
- 類名.靜態變量名
(1)static修飾屬性(類變量、靜態變量)
- 被static修飾的變量,叫靜態變量或類變量,可通過類名直接訪問;沒有被static修飾的變量,叫實例變量。
- 靜態變量為本類所有對象共享;實例變量只屬於單個對象。
- 靜態變量在內存中只有一個拷貝,在類加載時被創建和初始化,JVM只為其分配一次內存(節省內存)。類加載過程只進行一次,因此靜態變量也只會被創建一次;實例變量在創建對象時被初始化,在內存中有多個拷貝,每創建一個對象就會為其分配一次內存,各實例變量間互不影響(靈活)。
所以一般在需要實現以下兩個功能時使用靜態變量:
1).在對象之間共享值時;2).方便訪問變量時
(2)static修飾方法(靜態方法)
- static修飾的方法,叫靜態方法,可通過類名直接訪問,為本類所有對象共享;
- 靜態方法不能訪問本類的非靜態成員(包括實例變量和方法,因為非靜態則和特定的對象關聯,就不能全類共享了),但是非靜態方法可以訪問靜態成員(ofcourse,靜態成員全類共享);
- 靜態方法中不能出現this和super關鍵字(因為this是指向當前對象,super().成員名調用父類成員);
- 因為static方法獨立於任何實例,因此static方法必須被實現,而不能是抽象的abstract;
- 子類覆蓋父類的靜態方法時,只能依然覆蓋為靜態方法(一日static終生static),但是沒有多態。
Java中main方法必須為static的原因:
在類加載時無法創建對象,而靜態方法可以不通過對象調用,所以在類加載時可以通過main方法入口運行程序。
(3)static修飾代碼塊(初始化塊、靜態代碼塊)
格式: static{...}
static代碼塊也叫靜態代碼塊,是在類中獨立於類成員的static語句塊,可以有多個,位置可以隨便放,它不在任何的方法體內,JVM加載類時會執行這些靜態的代碼塊,如果static代碼塊有多個,JVM將按照它們在類中出現的先後順序依次執行它們,每個代碼塊只會被執行一次。
初始化總結(靜態變量->實例變量->按聲明初始化->執行構造方法)
1) 首次使用某個類時,JVM查找相應的類文件並加載(Java只有在必要時才會逐步載入相應的類文件)
首先為所有的靜態變量分配存儲空間並初始化為默認值(全局變量),然後按照聲明靜態變量時指定的初始化動作的順序,以及靜態初始化塊中的語句在類定義中出現的順序依次執行。這些靜態的初始化動作只會在其所屬類的類文件加載時執行一次。
2)類文件加載完畢後,如果需要創建類的對象,則進行如下初始化動作
JVM為所有的實例變量分配足夠的存儲空間並初始化為默認值(局部變量);然後按聲明實例變量時指定初值的初始化動作和實例初始化塊中的語句在類中出現的順序依次執行,之後再調用相應的構造方法。
4. abstract 和 interface 對比
stract class和interface是支持抽象類定義的兩種機制。正是由於這兩種機制的存在,才賦予了Java強大的面向對象能力。abstract class和interface之間在對於抽象類定義的支持方面具有很大的相似性,區別:
Abstract class | Interface | |
實例化 | 不能 | 不能 |
類 | 抽象類一般只能作為其他類的基類。一個類只能有一重繼承關系。 | 一個類可以實現多個interface |
數據成員 | 可有私有的,默認是friendly 型,其值可以在子類中重新定義,也可以重新賦值,可以非abstract | 不可有私有的,默認是public static final 型,且必須賦初值,實現類中不能重新定義,不能改變其值。 |
方法成員 | 可以私有的,可以有非abstract方法,必須實現 | 不可有私有的,默認是public,abstract 類型 |
設計理念 | 表示的是“is-a”關系 | 表示的是“like-a”關系 |
實現 | 需要繼承,要用extends | 需要實現,用implements |
抽象類(Abstract Class):
(1)只能作為其他類的基類,不能被實例化(new);
(2)抽象類中的成員是不是abstract無所謂,並不是必須的。(可以有抽象成員,也可以沒有任何抽象成員)
(3)抽象類不能同時是final的。抽象的總是希望被繼承,而final類不可被繼承。final和abstract不可同時存在。
(4)非抽象類繼承抽象類,必須覆蓋其所有的抽象成員。抽象類繼承抽象類,可以不覆蓋所有的抽象成員。
(5)抽象類允許被聲明
接口(interface):
接口的本質是一種特殊的抽象類,用來描述系統對外提供的所有服務。
(1)接口中,所有方法都是公開、抽象的:public abstract。(都必須被繼承)
(2)接口中,所有屬性都是公開、靜態、常量:public static final,且必須賦初值。(所有實現類共享且不可改變)
接口總是希望被實現被訪問的,因此所有成員都必須是公開的(public),確保外界可以訪問。接口僅僅描述系統可以做什麽,但不指明如何去做,具體操作由實現類完成,因此方法都是abstract的,都必須被繼承;接口不涉及任何的實現細節,因此無構造方法,接口不能被實例化;無變量,只有靜態常量(static final),因為要被所有的實現類共享;類的繼承只能單繼承,但是接口可以一次實現多個,用“,”隔開。
5. super 和 this對比
super:
super可以理解為是指向自己父類對象的一個指針,指的是離自己最近的一個父類。
用法:
- super.成員名(變量名或者方法名()):顯式調用父類的同名成員,當然成員不能是private的(不允許子類訪問)。因為當子類和父類存在同名成員時,因為子類成員優先級更高,此時會隱藏父類的相應成員。
- super(參數列表);:調用父類的構造函數,註意super語句一定要放在函數體的第一條 :
this:
this可以理解為指向當前對象自身的一個指針,即當前正在執行本方法的那個對象實例。位於函數體內部。
用法:
- this.成員名:引用成員變量。因為函數參數或者函數中的局部變量和成員變量同名的話,成員變量被屏蔽,此時要訪問成員變量則需要使用“this.成員變量”的方式引用。
- this(參數列表);:調用本類中參數表一致的另一個構造函數,註意應作為構造函數中的第一條語句。
引用構造函數時:
super(參數):調用父類中的某一個構造函數(應該為構造函數中的第一條語句)。 this(參數):調用本類中另一種形式的構造函數(應該為構造函數中的第一條語句)。this和super都無需聲明。
6. synchronize 和 volatile對比
(1)作用範圍:volatile僅能使用在變量級別;synchronized則可以使用在變量、方法、和類級別;
(2)volatile本質是在告訴jvm當前變量在寄存器(工作內存)中的值是不確定的,需要從主存中讀取;synchronized則是鎖定當前變量,只有當前線程可以訪問該變量,其他線程被阻塞住。
(3)volatile不會造成線程的阻塞;synchronized可能會造成線程的阻塞。
(4)volatile只能在線程內存和主內存之間同步一個變量的值,而synchronized則同步在線程內存和主內存之間的所有變量的值,通過鎖住和釋放監聽器來實現。
(5)volatile標記的變量不會被編譯器優化;synchronized標記的變量可以被編譯器優化
(6)顯然,synchronized在性能上將比volatile更加有所消耗
(7)volatile僅能實現變量的修改可見性,不能保證原子性;而synchronized則可以保證變量的修改可見性和原子性
詳細的 synchronize 和 volatile用法介紹請見博文:Java多線程(二) —— 線程安全、線程同步、線程間通信(含面試題集) 第二節【二、線程同步】
Java 面試總結 面試常問的關鍵字總結