常見面試問題整理系列之--Java基礎

1. 面向對象三大特性
面向對象三個基本特徵:封裝、繼承、多態;
Java語言以對象爲中心,最小單位爲類。
封裝:封裝就是隱藏一切可隱藏的東西,只向外界提供最簡單的編程接口;
繼承:繼承是從已有類獲得繼承信息建立新類的過程;
多態:多態是指容許不一樣子類型的對象對同一消息做出不一樣的響應。

2. 建立對象的方式
(1)使用new語句建立對象 這是最多見的方式
(2)使用反射手段,調用java.lang.Class或java.lang.reflect.Constructor類的newInstance()方法
(3)調用對象的clone方法 須要實現Cloneable接口
(4)運用反序列化手段 調用java.io.ObjectInputStream對象的readObject方法
(5)建立子類對象時,若是父類對象未被建立......
其中1,2,5都會調用構造函數,3是在內存上對已有對象的影印 因此不會調用構造函數,4是從文件中還原類的對象 也不會調用構造函數;
Class.newInstance只能調用無參的構造函數;Constructor.newInstance能夠調用有參和私有的構造函數;
Employee emp = (Employee) Class.forName("com.test.Employee").newInstance();
or
Employee emp = Employee.class.newInstance();

Constructor<Employee> constructor = Employee.class.getConstructor();
Employee emp2 = constructor.newInstance();

不管什麼時候調用一個對象的clone方法,JVM都會建立一個新的對象,將前面對象的內容所有拷貝進去;用clone方法建立對象並不會調用任何構造函數;要使用clone方法,咱們須要先實現Cloneable接口並實現其定義的clone方法
Employee emp3 = (Employee) emp2.clone();

爲了反序列化一個對象,咱們須要讓類實現Serializable接口;
ObjectInputStream in = new ObjectInputStream(new FileInputStream("data.obj"));
Employee emp4 = (Employee) in.readObject();

3. 什麼是對象的序列化與反序列化,用在什麼地方,如何使用
Java中的序列化指的是將對象轉換成以字節序列的形式來表示,這些字節序列包含了對象的數據信息,一個序列化後的對象能夠被寫到數據庫或文件中,也可用於網絡傳輸。通常當咱們使用緩存cache(內存空間不夠有可能會本地存儲到硬盤)或遠程調用RPC(網絡傳輸)的時候,常常須要讓咱們的實體類實現Serializable接口,目的就是讓其可序列化(交互雙方的一個公共標準);
序列化後的最終目的是爲了反序列化,恢復成原先的Java對象,因此序列化後的字節序列都是能夠恢復成Java對象的,這個過程就是反序列化;
一旦變量被transient修飾,變量將再也不是對象持久化的一部分,該變量內容在序列化後沒法得到訪問。也能夠認爲在將持久化的對象反序列化後,被transient修飾的變量將按照普通類成員變量同樣被初始化;
一個靜態變量無論是否被transient修飾,均不能被序列化,由於是類級別的;
最後,爲何要不被序列化呢,主要是爲了節省存儲空間。

4. JVM的實現原理、內存模型
Java語言既是編譯型語言,又是解釋型語言:Java源碼經過javac命令被編譯成.class文件,這種字節碼文件不面向任何平臺,只面向JVM(Java Virtual Machine);JVM是Java跨平臺的關鍵部分,其向上提供給Java字節碼程序的接口徹底相同,而向下適應不一樣平臺的接口則互不相同,爲特定平臺提供特定機器碼,使用java命令解釋執行;
程序計數器、虛擬機棧、本地方法棧3個區域隨線程而生,隨線程而滅,所以這幾個區域的內存分配和回收都具有肯定性,就不須要過多考慮回收的問題,由於方法結束或者線程結束時,內存天然就跟隨着回收了;而Java堆區和方法區的分配和回收是動態的,是GC須要關注的部分。

5. GC原理
要請求垃圾收集,能夠將相關對象設置爲null或調用System.gc() ,但後者將會嚴重影響代碼性能,由於通常每一次顯式調用System.gc()都會中止全部的響應,去檢查內存中是否有可回收的對象,這樣會對程序的正常運行形成極大的威脅。另外,調用該方法並不能保證JVM當即進行垃圾回收,僅僅是通知JVM要進行垃圾回收了,具體回收與否徹底由JVM決定,這樣作是費力不討好;
垃圾回收器一般是做爲一個單獨的低優先級的守護線程運行,不可預知的狀況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清除和回收;
有兩種算法能夠斷定對象是否存活:
(1)引用計數法,可是它很難解決兩個對象之間相互循環引用的狀況;
(2)可達性分析法,在主流的商用程序語言(如咱們的Java)的主流實現中,都是經過可達性分析算法來斷定對象是否存活的;
堆分新生代與老年代,具體操做流程:
新生代:包含Eden與兩個Survivor,剛剛新建的對象在Eden中,經歷一次Minor GC,Eden中的存活對象就會被移動到第一塊Survivor space S0,Eden被清空;等Eden區再滿了,就再觸發一次Minor GC,Eden和S0中的存活對象又被送入第二塊Survivor space S1,S0和Eden被清空,而後下一輪S0與S1交換角色,如此循環往復。若是對象的複製次數達到16次,該對象就會被送到老年代中;
與垃圾回收相關的JVM參數:
-Xms / -Xmx — 堆的初始大小 / 堆的最大大小
-Xmn — 堆中新生代的大小(同時設置XX:NewSize=XX:MaxNewSize),實際可用空間 = Eden + 1個Survivor,即90%
-Xss — 每一個線程堆棧的大小,通常來講若是棧不是很深的話,1M絕對夠用了
-XX:NewSize / -XX:MaxNewSize — 設置新生代大小/新生代最大大小
-XX:NewRatio — 新生代與老年代的比例,2表明新生代佔整個堆空間的1/3,老年代佔2/3
常見垃圾回收方式:
標記清除法:這是垃圾收集算法中最基礎的,分爲標記和清除兩個階段,它的思想是標記哪些要被回收的對象,而後統一回收。這種方法很簡單,可是效率不高,標記和清除的效率都很低。此外會產生大量不連續的內存碎片,從而致使之後程序在分配較大對象時因爲沒有充足的連續內存而提早觸發一次 GC 操做;
複製算法:爲了解決效率問題,複製算法將可用內存按容量劃分爲相等的兩部分,而後每次只使用其中的一塊,當一塊內存用完後就將還存活的對象複製到第二塊內存上,而後一次性清除完第一塊內存,再將第二塊上的對象複製到第一塊。可是這種方式內存的代價過高,每次基本上都要浪費一半的內存;因而將該算法進行了改進,內存區域再也不是按照1: 1去劃分,而是將內存劃分爲8: 1: 1三部分,較大那分內存是Eden區,其他是兩塊較小的內存區叫Survior區,每次都會優先使用Eden區,若Eden區滿則將對象複製到第二塊內存區上,而後清除Eden區,若是此時存活的對象太多,以致於Survivor不夠時,會將這些對象經過分配擔保機制複製到老年代中;
標記整理法:這種方法主要是爲了解決標記清除法產生大量內存碎片的問題。當對象存活率較高時,也解決了複製算法的效率問題。它的不一樣之處就是在清除對象的時候先將可回收對象移動到一端,而後清除掉端邊界之外的對象,這樣就不會產生內存碎片了,可是會增長停頓時間;
分代收集法:如今的虛擬機垃圾收集大多采用這種方式,它根據對象的生存週期,將堆分爲新生代和老年代。在新生代中,因爲對象生存期短,每次回收都會有大量對象死去,那麼這時就採用複製算法,新生代又分爲Eden和兩個Survivor,大小比例默認8: 1: 1。老年代裏的對象存活率較高,沒有額外的空間進行分配擔保,因此可使用標記整理法或標記清除法。
大對象直接進入老年代:JVM中有個參數配置-XX: PretenureSizeThreshold,令大於這個設置值的對象直接進入老年代,目的是爲了不在Eden和Survivor區之間發生大量的內存複製。
Java對象使用後設置爲null並不會減小內存佔用,設置爲null只是棧中指向的引用爲null,可是new出來的對象仍是存在於堆裏面的,須要等到GC算法調用時才能將沒有棧指向的對象給回收掉。

6. Java中的集合類有哪些
Java集合大體可分爲Set、List、Queue、Map四種體系;
Set:表明無序、不可重複;
List:表明有序、可重複;
Queue:表明一種隊列集合的實現;
Map:表明具備映射關係的集合。
Java集合主要有兩個接口派生而出:Collection和Map,Collection接口是Set、List、Queue接口的父接口;
Set與Collection基本相同,沒有額外提供其它方法,實際上Set就是Collection,只是行爲略有不一樣,Set不容許包含重複元素,添加同一對象兩次到集合中,第二次會操做失敗,add返回false;
List集合容許使用重複元素,能夠經過索引來訪問指定位置的元素;
Map與Set的關係:若是把Map裏全部key放在一塊兒看,它們就組成了一個Set集合(全部的key沒有順序,key與key之間不重複),實際上Map確實包含了一個keySet方法,用戶返回Map裏全部key組成的Set集合;
Map與List的關係:若是把Map裏全部value放在一塊兒看,它們就組成了一個List,元素與元素之間能夠重複,每一個元素能夠根據索引來查找,只是Map中索引再也不使用整數值,而是以另一個對象做爲索引。

7. LinkedList與ArrayList的區別
兩者都容許null元素;
ArrayList的內部實現是基於內部動態數組Object[],因此從概念上講,它更像數組,但LinkedList的內部實現是基於一組鏈接的記錄,因此它更像一個鏈表結構。ArrayList更適合get和set,由於LinkedList本質是雙向鏈表,須要從頭移動指針進行查找,而ArrayList能夠直接按序號索引元素;LinkedList更適合add和remove,由於ArrayList須要移動數據(直接在數組末尾add性能也很高,可是若是按照下標來插入、刪除元素,就須要經過Arrays.copyof函數來移動部分受影響的元素,性能變差);
ArrayList在要增長數據時,都會調用ensureCapacity方法來確保有足夠的容量。當容量不夠時,就設置新的容量爲舊容量的1.5倍(默認容量爲10),若是還不夠,就直接將容量設置爲所需容量,以後用Arrays.copyof方法將元素拷貝到新數組。所以,當容量不夠時,每次增長元素都須要將原來的元素拷貝到一個新數組中,很是耗時,所以建議在事先知道元素數量的狀況下再使用ArrayList,不然使用LinkedList;
ArrayList的空間浪費主要體如今在list列表的結尾預留必定的容量空間,而LinkedList的空間花費則體如今它的每個元素都須要消耗至關的空間,就存儲密度來講,ArrayList是優於LinkedList的;
總之,當操做是在一列數據的後面添加數據而不是在前面或中間,而且須要隨機地訪問其中的元素時,使用ArrayList會提供比較好的性能,當操做是在一列數據的前面或中間添加或刪除數據,而且按照順序訪問其中的元素時,就應該使用LinkedList了。

8. 對HashMap的理解
(1)HashMap的功能是經過key可以快速地找到value;
(2)HashMap是基於數組來實現哈希表的,數組就比如內存儲空間,數組的index就比如內存的地址;
(3)HashMap的每一個記錄就是一個Entry<K, V>對象,數組中存儲的就是這些對象,其中包含了key、value、hash、next四種結構元素;
(4)HashMap的哈希函數(put操做):當key爲空,經過putForNullKey方法把元素放到最開始位置(table[0]),不然根據傳遞的key值獲得hashCode(int hash=key.hashCode();),而後用這個hashCode與數組長度進行運算,獲得一個int值,就是Entry要存儲在數組的位置(下標);
(5)HashMap解決衝突:使用鏈地址法,每一個Entry對象都有一個引用next來指向鏈表的下一個Entry(若是鏈表長度超過閾值8,就把鏈表轉換成紅黑樹,鏈表長度低於6,就把紅黑樹轉回鏈表);
(6)HashMap的裝填因子:默認爲0.75(用於判斷是否須要擴展HashMap的容量,擴大爲原來的兩倍,HashMap的默認length是16);
(7)HashMap的get操做:當key爲空,則直接去哈希表的第一個位置table[0]對應的鏈表上查找,不然根據key算出hash值(數組下標),以後獲取對應的Entry,而後判斷Entry裏的key,hash值或者經過equals比較是否與要查找的相同,相同則返回value,不然遍歷該鏈表,直到找到爲止,不然返回null(在HashMap中,經過get方法返回null,多是HashMap中沒有該鍵,也多是該鍵對應的值爲null,所以不能用get方法判斷HashMap中是否存在某個鍵,須要使用containsKey方法);
(8)HashMap是非線程安全的,多線程環境下能夠採用concurrent併發包下的ConcurrentHashMap,或使用以下初始方式:Map m = Collections.synchronizedMap(new HashMap(...));
(9)HashMap實現了Serializable接口,所以支持序列化,實現了Cloneable接口,能被克隆。

9. hashCode與equals方法的關係
hashCode方法的存在是爲了減小equals方法的調用次數,從而提升程序效率;
若是equals方法獲得的結果爲true,兩個對象hashCode值一定相等;
若是equals方法獲得的結果爲false,兩個對象hashCode值不必定不一樣;
若是兩個對象hashCode值不等,equals方法的結果一定爲false;
若是兩個對象hashCode值相等,equals方法獲得的結果未知。
在重寫equals方法時,必須重寫hashCode方法。

10. HashMap與HashTable方法的區別
(1)兩者的存儲結構與解決衝突的方法都是相同的;
(2)HashTable在不指定容量的狀況下默認爲11,而HashMap爲16;HashTable不要求底層數組的容量必定要爲2的整數次冪,而HashMap則要求必定爲2的整數次冪;
(3)HashTable中的key和value都不容許爲null,而HashMap中key和value都容許爲null(key只能有一個爲null,value能夠有多個爲null);可是若是在HashTable中有相似put(null, null)的操做,編譯一樣能夠經過,由於key和value都是Object類型,但運行時會拋出NullPointerException異常;
(4)HashTable擴容時,將容量變爲原來的2倍+1,而HashMap擴容時,將容量變爲原來的2倍;
(5)HashTable計算hash值,直接用key的hashCode(),而HashMap從新計算了key的hash值;HashTable在求hash值對應的位置索引時,用的取模運算,而HashMap在求位置索引時,則用與運算,且這裏通常先用hash&0x7FFFFFFF後,再對length計算,目的是將負的hash值轉換爲正值;
(6)HashMap拿掉了HashTable的contains方法(比較的是value是不是equal的),由於此方法容易引發誤解;兩個類都包含containsKey和containsValue方法;
(7)HashTable是線程安全的,HashMap是線程非安全的。

11. 數組與鏈表的區別
數組的特色:
(1)在內存中,數組是一塊連續的區域,經過數組下標進行訪問,下標從0開始;
(2)數組須要預留空間,在使用前要先申請佔內存的大小,可能會浪費內存空間;
(3)插入和刪除數據效率低,插入數據時,這個位置後面的數據在內存中都要向後移;刪除數據時,這個數據後面的數據都要向前移;
(4)隨機讀取效率高,由於數組是連續的,知道每個數據的內存地址,能夠直接找到指定的數據;
(5)不利於擴展,數組定義的空間不夠時須要從新定義新數組而後複製。
數組的優勢:
(1)隨機訪問性強
(2)查找速度快
數組的缺點:
(1)插入和刪除效率低,由於要移動其它的元素
(2)可能浪費內存
(3)內存空間要求高,必須有足夠的連續內存空間
(4)數組大小固定,不能動態擴展
適用場景:
(1)頻繁查詢,對存儲空間要求不大,不多增長和刪除的狀況。
鏈表的特色:
(1)在內存中能夠存在在任何地方,不要求連續;
(2)每個數據都保存了下一個數據的內存地址,經過這個地址找到下一個數據;
(3)增長數據和刪除數據很容易;
(4)查找數據時效率很低,由於不具備隨機訪問性,因此訪問某個位置的數據都要從第一個數據開始;
(5)不指定大小,擴展方便,鏈表大小不用定義,數據隨意增刪。
鏈表的優勢:
(1)插入刪除速度快
(2)內存利用率高,不會浪費內存
(3)大小沒有固定,擴展靈活
(4)不須要初始化容量
鏈表的缺點:
(1)不能隨機查找,必須從第一個開始遍歷,查找效率低
(2)由於含有大量的指針域,佔用空間較大
適用場景:
(1)數據量較小,須要頻繁增長,刪除操做的場景。

12. 對類加載過程的理解
BootStrapClassLoader對應JRE/lib/rt.jar;
ExtClassLoader對應JRE/lib/ext/*.jar;
AppClassLoader對應Classpath指定的全部jar或目錄(默認的類加載器);
雙親委託機制:
當一個類加載器接收到一個類加載任務時,不會當即展開加載,而是將加載任務委託給它的父類加載器去執行,每一層的類加載器都採用相同的方式,直到委託給最頂層的啓動類加載器爲止。若是父類加載器沒法加載委託給它的類,便將類的加載任務退回給下一級類加載器去執行加載。

13. Java中如何使用JDBC建立一個事務並提交java

java.sql.Connection conn = null;
java.sql.PreparedStatement stmt = null;
try {
    conn = DriverManager.getConnection("jdbc:oracle:thin:@host:1521:SID", "username", "passwd");
    // 將自動提交設置爲false,若設置爲true,則數據庫會把每一次數據更新認定爲一個事務並自動提交
    conn.setAutoCommit(false);
    stmt = conn.createStatement();
    // 將A帳戶中的金額減小500
    stmt.execute("update t_account set amount = amount - 500 where account_id = 'A'");
    // 將B帳戶中的金額增長500
    stmt.execute("update t_account set amount = amount + 500 where account_id = 'B'");
    // 提交事務
    conn.commit();
} catch (Exception e){
        conn.rollback();
} finally {
    stmt.close();
    conn.close();
}

 
14. Java如何實現多繼承
使用內部類能夠實現多繼承,直接上代碼:程序員

public class Test {
    private class MyCall extends Call {
        
    }
    private class MySendMessage extends SendMessage {
        
    }
    private MyCall call = new MyCall();
    private MySendMessage sm = new MySendMessage();
    
    public void call(String phoneNumber) {
        call.call(phoneNumber);
    }
    public void send(String phoneNumber) {
        sm.send(phoneNumber);
    }
    
    public static void main(String[] args) {
        Test t = new Test();
        t.call("110");
        t.send("119");
    }
}
class Call {
    public void call(String phoneNumber) {
        System.out.println("call the number: " + phoneNumber);
    }
}
class SendMessage {
    public void send(String phoneNumber) {
        System.out.println("send the number: " + phoneNumber);
    }
}

 
15. String、StringBuilder、StringBuffer比較
三個類的主要區別在於運行速度與線程安全;
運行速度:StringBuilder > StringBuffer > String
緣由:StringBuilder和StringBuffer是變量,String是常量;若String str = "abc"; str += "de";,str被初始化爲abc,以後jvm建立一個新對象"abcde",將這個新對象賦值給str,而原來的"abc"會被垃圾回收機制回收,因此String對象的操做其實是一個不斷建立新對象而且將舊對象回收的過程;而對StringBuilder和StringBuffer的操做是直接對變量進行更改,不包含對象的建立與回收操做;
String str = "abc" + "de"; //這個操做做用和String str = "abcde";相同,因此會很快,
String str1 = "abc", str2 = "de"; str1 = str1 + str2; //這個操做會很慢;
線程安全:StringBuilder是線程不安全的,StringBuffer是線程安全的;
String:適用於少許的字符串操做的狀況;
StringBuilder:適用於單線程下在字符緩衝區進行大量操做的狀況;
StringBuffer:適用多線程下在字符緩衝區進行大量操做的狀況。

16. String與Integer的轉換
Integer轉換爲String:
Integer i = 1;
System.out.println(i.toString());
System.out.println(Integer.toString(i));
System.out.println(String.valueOf(i));
String轉換爲Integer:
String str = "...";
Integer i = null;
if (str != null) {
    i = Integer.valueOf(str);
}
(也可使用構造方法)

17. Java中去除字符串空格用什麼函數
trim:去掉首尾的空格;
replace:去掉全部的空格,包括首尾、中間;將oldchar替換爲newchar;
str = str.replace(" ", ""); //去掉全部空格;
replaceAll:去掉全部的空格;參數爲regex(正則表達式);
str = str.replaceAll("\\s*", ""); //替換大部分空白字符,不限於空格;
str = str.replaceAll(" +", ""); //去掉全部空格;
\s能夠匹配空格、製表符、換頁符等空白字符的其中任意一個。

18. 自動裝箱與拆箱的原理
自動裝箱:當給一個Integer對象賦int值時,會調用Integer.valueOf方法,若是數值在-128~127之間,就會被緩存在內存中;若是不在這個範圍內,就去new一個Integer對象。
自動拆箱:做用在包裝類型上的二元運算符會致使拆箱操做,拆箱的實質是調用intValue方法;而==與!=二元運算符比較特殊,一個包裝類型和一個基本類型或表達式(即包含算數運算)進行==或!=比較,會首先對包裝類型進行拆箱操做,以後再比較;而對兩個包裝類型進行==或!=操做,會直接比較對象地址。

19. 值傳遞與引用傳遞的原理
值傳遞:函數接收的是原始值的一個copy,此時內存中存在兩個相等的基本類型,即實際參數和形式參數,後面方法的操做都是對形參的修改,不影響實際參數的值;
引用傳遞:函數接收的是原始值的內存地址,在方法執行中,形參和實參內容相同,指向同一塊內存地址,方法執行中對引用的操做將會影響到實際對象;
public void swap(Student x, Student y) {
    Student temp = x;
    x = y;
    y = temp;
}
swap方法執行過程:
(1)將對象a、b的拷貝分別賦給x、y,此時a和x指向同一對象,b和y指向同一對象;
(2)swap方法完成x、y的交換,a、b並無變化;
(3)方法執行完畢,x、y再也不使用,a、b依舊指向以前的對象;
綜上,Java的參數傳遞方式爲:值傳遞。

20. 方法覆蓋與方法重載的比較
方法重載:發生在編譯時,被稱爲編譯時多態,編譯器能夠根據參數類型選擇使用哪一個方法;
方法覆蓋(重寫):發生在運行時,被稱爲運行時多態,由於在編譯期編譯器不知道也無法知道去調用哪一個方法,JVM會在代碼運行時作出決定;
方法的重寫要遵循「兩同兩小一大」規則,「兩同」即方法名相同、形參列表相同;「兩小」即子類方法返回值類型應比父類方法返回值類型更小或相等,子類方法聲明拋出異常類應該比父類方法聲明拋出的異常類更小或相等;「一大」指的是子類方法的訪問權限應比父類方法的權限更大或相等;尤爲須要指出的是,覆蓋方法和被覆蓋方法要麼都是類方法,要麼都是實例方法,不能一個是類方法,一個是實例方法;
方法重載只與「兩同一不一樣」有關:同類名,同方法名,不一樣參數列表。

21. 接口與抽象類的比較
(1)接口是公開的,public static final的Field,public abstract的method;抽象類能夠有私有方法和私有變量,能夠有構造器;
(2)接口是has-a關係;抽象類是is-a關係;
(3)一個類只能繼承一次,可是能夠實現多個接口;
(4)通常的應用,最頂層是接口,以後是抽象類,而後是實現類;
(5)舉例:Door具備open和close功能,若是如今想添加一個報警功能alarm,最好的方案是設計一個抽象類Door,包含open和close方法;再設計一個接口包含alarm方法;由於Door都具備open和close方法而不必定具備alarm功能,具備alarm功能的不必定是Door,open與alarm本質上不是同一個層面上的東西;open和close對於Door來講是is-a關係,alarm對於Door來講是has-a關係。

22. 泛型的做用
Java1.5引入了泛型,全部的集合接口都在使用它。做用:
(1)泛型容許咱們爲集合提供一個能夠容納的對象類型,所以,若是你添加其它類型的任何元素,它會在編譯時報錯;這避免了在運行時出現ClassCastException,由於你將在編譯時獲得報錯信息;
(2)泛型也使得代碼整潔,咱們不須要使用顯式轉換和instanceof操做符。

23. 什麼是迭代器(Iterator)
迭代器是一種設計模式,它是一個對象,能夠遍歷並選擇序列中的對象,而開發人員不須要了解該序列的底層結構;
java.lang.Iterable接口,被Collection繼承;
iterator方法在set和list接口中都有定義,可是ListIterator僅存在於list接口中(或實現類中);
ListIterator有add方法,能夠向List中添加對象,而Iterator不能;
ListIterator和Iterator都有hasNext和next方法,能夠實現順序向後遍歷,可是ListIterator有hasPrevious和previous方法,能夠實現逆向(順序向前)遍歷,Iterator就不能夠;
ListIterator能夠定位當前的索引位置,nextIndex和previousIndex能夠實現,Iterator沒有此功能;
均可實現刪除對象,可是ListIterator能夠實現對象的修改,set方法能夠實現,Iierator僅能遍歷,不能修改。 

24. Error與Exception的比較
Java將全部的錯誤封裝成一個對象,其根本父類爲Throwable,Throwable有兩個子類Error和Exception;
Error是Throwable的子類,用於指示合理的應用程序(JVM)不該該試圖捕獲的嚴重問題;
Exception類及其子類是Throwable的一種表現形式,它指出了合理的應用程序(JVM)想要捕獲的條件;
RuntimeException是可能在Java虛擬機正常運行期間拋出的異常的超類,無需在throws中進行說明。RuntimeException也被稱爲未檢查異常(unchecked Exception)(其他的Exception爲已檢查異常),未檢查異常是由於程序員沒有進行必要的檢查,由於疏忽和錯誤而引發的異常;
已檢查異常:定義方法時必須聲明全部可能會拋出的已檢查異常;在調用這個方法時,必須對其進行捕獲,不然就將其傳遞下去。

25. 成員變量與局部變量的比較
成員變量:方法外部,類的內部定義的變量,成員變量存儲在堆中的對象裏面,由垃圾回收器負責回收;
局部變量:方法或語句塊內部定義的變量,形式參數是局部變量,局部變量的數據存放於棧內存中。棧內存中的局部變量隨着方法的消失而消失,不能使用訪問控制符。
成員變量無需顯式初始化;局部變量分爲形參、方法局部變量、代碼塊局部變量,除了形參以外,局部變量都必須顯式初始化。
在同一個類裏,成員變量的做用範圍是整個類內有效,一個類裏不能定義兩個同名的成員變量,即便一個是類Field,一個是實例Field也不行;
一個方法裏不能定義兩個同名的局部變量,即便一個是方法局部變量,一個是代碼塊局部變量或形參也不行;
Java容許局部變量和成員變量同名,若是方法裏的局部變量和成員變量同名,局部變量會覆蓋成員變量,若是須要在這個方法裏引用被覆蓋的成員變量,則可使用this(對於實例Field)或類名(對於類Field)做爲調用者來限定訪問成員變量。正則表達式

相關文章
相關標籤/搜索