1.String 是最基本的數據類型嗎?
不是。Java 中的基本數據類型只有 8 個 :byte、short、int、long、float、double、
char、boolean;除了基本類型(primitive type),剩下的都是引用類型(reference
type),Java 5 之後引入的枚舉類型也算是一種比較特殊的引用類型。java
2.float f=3.4;是否正確?
不正確。3.4 是雙精度數,將雙精度型(double)賦值給浮點型(float)屬於程序員
下轉型(down-casting,也稱爲窄化)會形成精度損失,所以須要強制類型轉換面試
float f =(float)3.4; 或者寫成 float f =3.4F;。算法
3.short s1 = 1; s1 = s1 + 1;有錯嗎?short s1 = 1; s1 += 1?
對於 short s1 = 1; s1 = s1 + 1;因爲 1 是 int 類型,所以 s1+1 運算結果也是 int型,須要強制轉換類型才能賦值給 short 型。而 short s1 = 1; s1 += 1;能夠正確編譯,由於 s1+= 1;至關於 s1 = (short)(s1 + 1);其中有隱含的強制類型轉換。數據庫
4.Java 有沒有 goto?
goto 是 Java 中的保留字,在目前版本的 Java 中沒有使用。(根據 James Gosling編程
(Java 之父)編寫的《The Java Programming Language》一書的附錄中給出設計模式
了一個 Java 關鍵字列表,其中有 goto 和 const,可是這兩個是目前沒法使用的數組
關鍵字,所以有些地方將其稱之爲保留字,其實保留字這個詞應該有更普遍的意緩存
義,由於熟悉 C 語言的程序員都知道,在系統類庫中使用過的有特殊意義的單詞安全
或單詞的組合都被視爲保留字)
5.int 和 Integer 有什麼區別?
Java 是一個近乎純潔的面向對象編程語言,可是爲了編程的方便仍是引入了基本
數據類型,可是爲了可以將這些基本數據類型當成對象操做,Java 爲每個基本
數據類型都引入了對應的包裝類型(wrapper class),int 的包裝類就是 Integer,
從 Java 5 開始引入了自動裝箱/拆箱機制,使得兩者能夠相互轉換
6.&和&&的區別?
&運算符有兩種用法:
(1)按位與;
(2)邏輯與。
&&運算符是短路與運算。邏輯與跟短路與的差異是很是巨大的,雖然兩者都要求運算符左右兩端的布爾值都是true 整個表達式的值纔是 true。&&之因此稱爲短路運算是由於,若是&&左邊的表達式的值是 false,右邊的表達式會被直接短路掉,不會進行運算。不少時候咱們可能都須要用&&而不是&,例如在驗證用戶登陸時斷定用戶名不是 null 並且不是空字符串,應當寫爲:username != null &&!username.equals(「」),兩者的順序不能交換,更不能用&運算符,由於第一個條件若是不成立,根本不能進行字符串的 equals 比較,不然會產生 NullPointerException 異常。注意:邏輯或運算符(|)和短路或運算符(||)的差異也是如此。
補充:若是你熟悉 JavaScript,那你可能更能感覺到短路運算的強大,想成爲JavaScript 的高手就先從玩轉短路運算開始吧
7.解釋內存中的棧(stack)、堆(heap)和方法區(method area)的用法
一般咱們定義一個基本數據類型的變量,一個對象的引用,還有就是函數調用的現場保存都使用JVM中的棧空間;而經過new關鍵字和構造器建立的對象則放在堆空間,堆是垃圾收集器管理的主要區域,因爲如今的垃圾收集器都採用分代收集算法,因此堆空間還能夠細分爲新生代和老生代,再具體一點能夠分爲Eden、Survivor(又可分爲FromSurvivor和ToSurvivor)、Tenured;方法區和堆都是各個線程共享的內存區域,用於存儲已經被JVM加載的類信息、常量、靜態變量、JIT編譯器編譯後的代碼等數據;程序中的字面量(literal)如直接書寫的100、」hello」和常量都是放在常量池中,常量池是方法區的一部分,。棧空間操做起來最快可是棧很小,一般大量的對象都是放在堆空間,棧和堆的大小均可以經過JVM的啓動參數來進行調整,棧空間用光了會引起StackOverflowError,而堆和常量池空間不足則會引起OutOfMemoryError。
補充 1:較新版本的 Java(從 Java 6 的某個更新開始)中,因爲 JIT 編譯器的發
展和」逃逸分析」技術的逐漸成熟,棧上分配、標量替換等優化技術使得對象一
定分配在堆上這件事情已經變得不那麼絕對了。
補充 2:運行時常量池至關於 Class 文件常量池具備動態性,Java 語言並不要求
常量必定只有編譯期間才能產生,運行期間也能夠將新的常量放入池中,String
類的 intern()方法就是這樣的。
8.Math.round(11.5)等於多少?Math.round(-11.5)等於多少?
Math.round(11.5)的返回值是12,Math.round(-11.5)的返回值是-11。四捨五入的原理是在參數上加0.5而後進行下取整
9.switch是否能做用在byte上,是否能做用在long上,是否能做用在String上?
在Java5之前,switch(expr)中,expr只能是byte、short、char、int。從Java5開始,Java中引入了枚舉類型,expr也能夠是enum類型,從Java7開始,expr還能夠是字符串(String),可是長整型(long)在目前全部的版本中都是不能夠的。
11.用最有效率的方法計算2乘以8?
2<<3(左移3位至關於乘以2的3次方,右移3位至關於除以2的3次方)。補充:咱們爲編寫的類重寫hashCode方法時,可能會看到以下所示的代碼,其實咱們不太理解爲何要使用這樣的乘法運算來產生哈希碼(散列碼),並且爲何這個數是個素數,爲何一般選擇31這個數?前兩個問題的答案你能夠本身百度一下,選擇31是由於能夠用移位和減法運算來代替乘法,從而獲得更好的性能。說到這裏你可能已經想到了:31*num等價於(num<<5)-num,左移5位至關於乘以2的5次方再減去自身就至關於乘以31,如今的VM都能自動完成這個優化
12.數組有沒有 length()方法?String 有沒有 length()方法?
數組沒有 length()方法 ,有 length 的屬性。String 有 length()方法。JavaScript中,得到字符串的長度是經過 length 屬性獲得的,這一點容易和 Java 混淆。
13.在 Java 中,如何跳出當前的多重嵌套循環?
在最外層循環前加一個標記如A,而後用breakA;能夠跳出多重循環。(Java中支持帶標籤的break和continue語句,做用有點相似於C和C++中的goto語句,可是就像要避免使用goto同樣,應該避免使用帶標籤的break和continue,由於它不會讓你的程序變得更優雅,不少時候甚至有相反的做用,因此這種語法其實不知道更好)
14. 構造器(constructor)是否可被重寫(override)?
構造器不能被繼承,所以不能被重寫,但能夠被重載。
15.兩個對象值相同(x.equals(y) == true),但卻可有不一樣的hash code,這句話對不對?
不對,若是兩個對象 x 和 y 知足 x.equals(y) == true,它們的哈希碼(hash code)應當相同。Java 對於 eqauls 方法和 hashCode 方法是這樣規定的:
(1)若是兩個對象相同(equals方法返回true),那麼它們的hashCode值必定要相同;
(2)若是兩個對象的hashCode相同,它們並不必定相同。固然,你未必要按照要求去作,可是若是你違背了上述原則就會發如今使用容器時,相同的對象能夠出如今Set集合中,同時增長新元素的效率會大大降低(對於使用哈希存儲的系統,若是哈希碼頻繁的衝突將會形成存取性能急劇降低)。
16.是否能夠繼承 String 類?
String 類是 final 類,不能夠被繼承。
補充:繼承 String 自己就是一個錯誤的行爲,對 String 類型最好的重用方式是關聯關係(Has-A)和依賴關係(Use-A)而不是繼承關係(Is-A)。
17.當一個對象被看成參數傳遞到一個方法後,此方法可改變這個對象的屬性,並可返回變化後的結果,那麼這裏究竟是值傳遞仍是引用傳遞?
是值傳遞。Java語言的方法調用只支持參數的值傳遞。當一個對象實例做爲一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的屬性能夠在被調用過程當中被改變,但對對象引用的改變是不會影響到調用者的。C++和C#中能夠經過傳引用或傳輸出參數來改變傳入的參數的值。在C#中能夠編寫以下所示的代碼,可是在Java中卻作不到。
18.String 和 StringBuilder、StringBuffer 的區別?
Java 平臺提供了兩種類型的字符串:String 和 StringBuffer/StringBuilder,它們能夠儲存和操做字符串。其中 String 是隻讀字符串,也就意味着 String 引用的字符串內容是不能被改變的。而 StringBuffer/StringBuilder 類表示的字符串對象能夠直接進行修改。StringBuilder 是 Java 5 中引入的,它和 StringBuffer 的方法徹底相同,區別在於它是在單線程環境下使用的,由於它的全部方面都沒有被synchronized 修飾,所以它的效率也比 StringBuffer 要高。
19.重載(Overload)和重寫(Override)的區別。重載的方法可否根據返回類型進行區分?
方法的重載和重寫都是實現多態的方式,區別在於前者實現的是編譯時的多態性,然後者實現的是運行時的多態性。
重載發生在一個類中,同名的方法若是有不一樣的參數列表(參數類型不一樣、參數個數不一樣或者兩者都不一樣)則視爲重載;
重寫發生在子類與父類之間,重寫要求子類被重寫方法與父類被重寫方法有相同的返回類型,比父類被重寫方法更好訪問,不能比父類被重寫方法聲明更多的異常(里氏代換原則)。重載對返回類型沒有特殊的要求。
20.描述一下 JVM 加載 class 文件的原理機制?
JVM中類的裝載是由類加載器(ClassLoader)和它的子類來實現的,Java中的類加載器是一個重要的Java運行時系統組件,它負責在運行時查找和裝入類文件中的類。
因爲Java的跨平臺性,通過編譯的Java源程序並非一個可執行程序,而是一個或多個類文件。當Java程序須要使用某個類時,JVM會確保這個類已經被加載、鏈接(驗證、準備和解析)和初始化。
類的加載是指把類的.class文件中的數據讀入到內存中,一般是建立一個字節數組讀入.class文件,而後產生與所加載類對應的Class對象。加載完成後,Class對象還不完整,因此此時的類還不可用。
當類被加載後就進入鏈接階段,這一階段包括驗證、準備(爲靜態變量分配內存並設置默認的初始值)和解析(將符號引用替換爲直接引用)三個步驟。
最後JVM對類進行初始化,包括:
1)若是類存在直接的父類而且這個類尚未被初始化,那麼就先初始化父類;
2)若是類中存在初始化語句,就依次執行這些初始化語句。
類的加載是由類加載器完成的,類加載器包括:根加載器(BootStrap)、擴展加載器(Extension)、系統加載器(System)和用戶自定義類加載器(java.lang.ClassLoader的子類)。從Java2(JDK1.2)開始,類加載過程採起了父親委託機制(PDM)。
PDM更好的保證了Java平臺的安全性,在該機制中,JVM自帶的Bootstrap是根加載器,其餘的加載器都有且僅有一個父類加載器。類的加載首先請求父類加載器加載,父類加載器無能爲力時才由其子類加載器自行加載
21.char 型變量中能不能存貯一箇中文漢字,爲何?
char 類型能夠存儲一箇中文漢字,由於 Java 中使用的編碼是 Unicode(不選擇
任何特定的編碼,直接使用字符在字符集中的編號,這是統一的惟一方法),一
個 char 類型佔 2 個字節(16 比特),因此放一箇中文是沒問題的。##
22. 抽象類(abstract class)和接口(interface)有什麼異同?
抽象類和接口都不可以實例化,但能夠定義抽象類和接口類型的引用。一個類若是繼承了某個抽象類或者實現了某個接口都須要對其中的抽象方法所有進行實現,不然該類仍然須要被聲明爲抽象類。
接口比抽象類更加抽象,由於抽象類中能夠定義構造器,能夠有抽象方法和具體方法,而接口中不能定義構造器並且其中的方法所有都是抽象方法。
抽象類中的成員能夠是private、默認、protected、public的,而接口中的成員全都是public的。
抽象類中能夠定義成員變量,而接口中定義的成員變量實際上都是常量。有抽象方法的類必須被聲明爲抽象類,而抽象類未必要有抽象方法。
23.Java 中會存在內存泄漏嗎,請簡單描述。
理論上Java由於有垃圾回收機制(GC)不會存在內存泄露問題(這也是Java被普遍使用於服務器端編程的一個重要緣由);然而在實際開發中,可能會存在無用但可達的對象,這些對象不能被GC回收,所以也會致使內存泄露的發生。例如Hibernate的Session(一級緩存)中的對象屬於持久態,垃圾回收器是不會回收這些對象的,然而這些對象中可能存在無用的垃圾對象,若是不及時關閉(close)或清空(flush)一級緩存就可能致使內存泄露。下面例子中的代碼也會致使內存泄露。
24.抽象的(abstract)方法是否可同時是靜態的(static),是否可同時是本地方法(native),是否可同時被 synchronized修飾?
都不能。抽象方法須要子類重寫,而靜態的方法是沒法被重寫的,所以兩者是矛盾的。本地方法是由本地代碼(如 C 代碼)實現的方法,而抽象方法是沒有實現的,也是矛盾的。synchronized 和方法的實現細節有關,抽象方法不涉及實現細節,所以也是相互矛盾的
25. 闡述靜態變量和實例變量的區別。
靜態變量是被 static 修飾符修飾的變量,也稱爲類變量,它屬於類,不屬於類的任何一個對象,一個類無論建立多少個對象,靜態變量在內存中有且僅有一個拷貝;實例變量必須依存於某一實例,須要先建立對象而後經過對象才能訪問到它。靜態變量能夠實現讓多個對象共享內存。
補充:在 Java 開發中,上下文類和工具類中一般會有大量的靜態成員。
26.是否能夠從一個靜態(static)方法內部發出對非靜態(non-static)方法的調用?
不能夠,靜態方法只能訪問靜態成員,由於非靜態方法的調用要先建立對象,在調用靜態方法時可能對象並無被初始化。
27.如何實現對象克隆?
有兩種方式:
1). 實現 Cloneable 接口並重寫 Object 類中的 clone()方法;
2). 實現 Serializable 接口,經過對象的序列化和反序列化實現克隆,能夠實現真正的深度克隆
28.GC 是什麼?爲何要有 GC?
GC是垃圾收集的意思,內存處理是編程人員容易出現問題的地方,忘記或者錯誤的內存回收會致使程序或系統的不穩定甚至崩潰,Java提供的GC功能能夠自動監測對象是否超過做用域從而達到自動回收內存的目的,Java語言沒有提供釋放已分配內存的顯示操做方法。Java程序員不用擔憂內存管理,由於垃圾收集器會自動進行管理。要請求垃圾收集,能夠調用下面的方法之一:System.gc()或Runtime.getRuntime().gc(),但JVM能夠屏蔽掉顯示的垃圾回收調用。
垃圾回收能夠有效的防止內存泄露,有效的使用可使用的內存。垃圾回收器一般是做爲一個單獨的低優先級的線程運行,不可預知的狀況下對內存堆中已經死亡的或者長時間沒有使用的對象進行清除和回收,程序員不能實時的調用垃圾回收器對某個對象或全部對象進行垃圾回收。在Java誕生初期,垃圾回收是Java最大的亮點之一,由於服務器端的編程須要有效的防止內存泄露問題,然而時過境遷,現在Java的垃圾回收機制已經成爲被詬病的東西。移動智能終端用戶一般以爲iOS的系統比Android系統有更好的用戶體驗,其中一個深層次的緣由就在於Android系統中垃圾回收的不可預知性。
補充:垃圾回收機制有不少種,包括:分代複製垃圾回收、標記垃圾回收、增量垃圾回收等方式。標準的Java進程既有棧又有堆。棧保存了原始型局部變量,堆保存了要建立的對象。Java平臺對堆內存回收和再利用的基本算法被稱爲標記和清除,可是Java對其進行了改進,採用「分代式垃圾收集」。這種方法會跟Java對象的生命週期將堆內存劃分爲不一樣的區域,在垃圾收集過程當中,可能會將對象移動到不一樣區域:
伊甸園(Eden):這是對象最初誕生的區域,而且對大多數對象來講,這裏是它們惟一存在過的區域。
倖存者樂園(Survivor):從伊甸園倖存下來的對象會被挪到這裏。
終身頤養園(Tenured):這是足夠老的倖存對象的歸宿。
年輕代收集(Minor-GC)過程是不會觸及這個地方的。當年輕代收集不能把對象放進終身頤養園時,就會觸發一次徹底收集(Major-GC),這裏可能還會牽扯到壓縮,以便爲大對象騰出足夠的空間。
與垃圾回收相關的 JVM 參數:
· -Xms / -Xmx — 堆的初始大小 / 堆的最大大小
· -Xmn — 堆中年輕代的大小
· -XX:-DisableExplicitGC — 讓 System.gc()不產生任何做用
· -XX:+PrintGCDetails — 打印 GC 的細節
· -XX:+PrintGCDateStamps — 打印 GC 操做的時間戳
· -XX:NewSize / XX:MaxNewSize — 設置新生代大小/新生代最大大小
· -XX:NewRatio — 能夠設置老生代和新生代的比例
· -XX:PrintTenuringDistribution — 設置每次新生代 GC 後輸出倖存者
樂園中對象年齡的分佈
· -XX:InitialTenuringThreshold / -XX:MaxTenuringThreshold:設置老
年代閥值的初始值和最大值
· -XX:TargetSurvivorRatio:設置倖存區的目標使用率
29.String s = new String(「xyz」);建立了幾個字符串對象?
兩個對象,一個是靜態區的」xyz」,一個是用 new 建立在堆上的對象。
30. 接口是否可繼承(extends)接口?抽象類是否可實現
接口能夠繼承接口,並且支持多重繼承。抽象類能夠實現(implements)接口,抽象類可繼承具體類也能夠繼承抽象類。
31.一個」.java」源文件中是否能夠包含多個類(不是內部類)?有什麼限制?
能夠,但一個源文件中最多隻能有一個公開類(public class)並且文件名必須和公開類的類名徹底保持一致。
32. Anonymous Inner Class(匿名內部類)是否能夠繼承其它類?是否能夠實現接口?
能夠繼承其餘類或實現其餘接口,在 Swing 編程和 Android 開發中經常使用此方式來實現事件監聽和回調。
33.內部類能夠引用它的包含類(外部類)的成員嗎?有沒有什麼限制?
一個內部類對象能夠訪問建立它的外部類對象的成員,包括私有成員。
34.Java 中的 final 關鍵字有哪些用法?
(1)修飾類:表示該類不能被繼承
(2)修飾方法:表示方法不能被重寫
(3)修飾變量:表示變量只能一次賦值之後值不能被修改(常量)。
35.數據類型之間的轉換
調用基本數據類型對應的包裝類中的方法 parseXXX(String)或valueOf(String)便可返回相應基本類型
一種方法是將基本數據類型與空字符串(」「)鏈接(+)便可得到其所對應的字符串;另外一種方法是調用 String 類中的 valueOf()方法返回相應字符串
36.Error 和 Exception 有什麼區別?
Error 表示系統級的錯誤和程序沒必要處理的異常,是恢復不是不可能但很困難的情
況下的一種嚴重問題;好比內存溢出,不可能期望程序能處理這樣的狀況;
Exception 表示須要捕捉或者須要程序進行處理的異常,是一種設計或實現問題;
也就是說,它表示若是程序運行正常,從不會發生的狀況。
37.try{}裏有一個 return 語句,那麼緊跟在這個 try 後的finally{}裏的代碼會不會被執行,何時被執行,在 return前仍是後?
會執行,在方法返回調用者前執行。
注意:在 finally 中改變返回值的作法是很差的,由於若是存在 finally 代碼塊,try
中的 return 語句不會立馬返回調用者,而是記錄下返回值待 finally 代碼塊執行完
畢以後再向調用者返回其值,而後若是在 finally 中修改了返回值,就會返回修改
後的值。顯然,在 finally 中返回或者修改返回值會對程序形成很大的困擾,C#中
直接用編譯錯誤的方式來阻止程序員幹這種齷齪的事情,Java 中也能夠經過提高編譯器的語法檢查級別來產生警告或錯誤,Eclipse 中能夠在如圖所示的地方進行
設置,強烈建議將此項設置爲編譯錯誤。
38.Java 語言如何進行異常處理,關鍵字:throws、throw、try、catch、finally 分別如何使用?
Java 經過面向對象的方法進行異常處理,把各類不一樣的異常進行分類,並提供了良好的接口。在 Java 中,每一個異常都是一個對象,它是 Throwable 類或其子類的實例。當一個方法出現異常後便拋出一個異常對象,該對象中包含有異常信息,調用這個對象的方法能夠捕獲到這個異常並能夠對其進行處理。
Java的異常處理是經過5個關鍵詞來實現的:try、catch、throw、throws和finally。通常狀況下是用try來執行一段程序,
若是系統會拋出(throw)一個異常對象,能夠經過它的類型來捕獲(catch)它,或經過老是執行代碼塊(finally)來處理;
try用來指定一塊預防全部異常的程序;
catch子句緊跟在try塊後面,用來指定你想要捕獲的異常的類型;throw語句用來明確地拋出一個異常;
throws用來聲明一個方法可能拋出的各類異常(固然聲明異常時容許無病呻吟);
finally爲確保一段代碼無論發生什麼異常情況都要被執行;
try語句能夠嵌套,每當遇到一個try語句,異常的結構就會被放入異常棧中,直到全部的try語句都完成。若是下一級的try語句沒有對某種異常進行處理,異常棧就會執行出棧操做,直到遇到有處理這種異常的try語句或者最終將異常拋給JVM。
39.運行時異常與受檢異常有何異同?
異常表示程序運行過程當中可能出現的非正常狀態,運行時異常表示虛擬機的一般操做中可能遇到的異常,是一種常見運行錯誤,只要程序設計得沒有問題一般就不會發生。受檢異常跟程序運行的上下文環境有關,即便程序設計無誤,仍然可能因使用的問題而引起。Java 編譯器要求方法必須聲明拋出可能發生的受檢異常,可是並不要求必須聲明拋出未被捕獲的運行時異常。異常和繼承同樣,是面向對象程序設計中常常被濫用的東西,在 Effective Java 中對異常的使用給出瞭如下指導原則:
不要將異常處理用於正常的控制流(設計良好的 API 不該該強迫它的調用者爲了正常的控制流而使用異常)
· 對能夠恢復的狀況使用受檢異常,對編程錯誤使用運行時異常
· 避免沒必要要的使用受檢異常(能夠經過一些狀態檢測手段來避免異常的發生)
優先使用標準的異常
· 每一個方法拋出的異常都要有文檔
· 保持異常的原子性
· 不要在 catch 中忽略掉捕獲到的異常
40.列出一些你常見的運行時異常?
ArithmeticException(算術異常)
ClassCastException (類轉換異常)
IllegalArgumentException (非法參數異常)
IndexOutOfBoundsException (下標越界異常)
NullPointerException (空指針異常)
SecurityException (安全異常)
41 .闡述 final、finally、finalize 的區別。
final:修飾符(關鍵字)有三種用法:若是一個類被聲明爲 final,意味着它不能再派生出新的子類,即不能被繼承,所以它和 abstract 是反義詞。將變量聲明爲 final,能夠保證它們在使用中不被改變,被聲明爲 final 的變量必須在聲明時給定初值,而在之後的引用中只能讀取不可修改。被聲明爲 final 的方法也一樣只能使用,不能在子類中被重寫。
finally:一般放在 try…catch…的後面構造老是執行代碼塊,這就意味着
程序不管正常執行仍是發生異常,這裏的代碼只要 JVM 不關閉都能執行,能夠
將釋放外部資源的代碼寫在 finally 塊中。
finalize:Object 類中定義的方法,Java 中容許使用 finalize()方法在垃
圾收集器將對象從內存中清除出去以前作必要的清理工做。這個方法是由垃圾收
集器在銷燬對象時調用的,經過重寫 finalize()方法能夠整理系統資源或者執行
其餘清理工做。
42.List、Set、Map 是否繼承自 Collection 接口?
List、Set 是 ,Map 不是。Map 是鍵值對映射容器,與 List 和 Set 有明顯的區別,而 Set 存儲的零散的元素且不容許有重複元素(數學中的集合也是如此),List是線性結構的容器,適用於按數值索引訪問元素的情形
43.闡述 ArrayList、Vector、LinkedList 的存儲性能和特性
ArrayList和Vector都是使用數組方式存儲數據,此數組元素數大於實際存儲的數據以便增長和插入元素,它們都容許直接按序號索引元素,可是插入元素要涉及數組元素移動等內存操做,因此索引數據快而插入數據慢,Vector中的方法因爲添加了synchronized修飾,所以Vector是線程安全的容器,但性能上較
ArrayList差,所以已是Java中的遺留容器。LinkedList使用雙向鏈表實現存儲(將內存中零散的內存單元經過附加的引用關聯起來,造成一個能夠按序號索引的線性結構,這種鏈式存儲方式與數組的連續存儲方式相比,內存的利用率更高),按序號索引數據須要進行前向或後向遍歷,可是插入數據時只須要記錄本項的先後項便可,因此插入速度較快。Vector屬於遺留容器(Java早期的版本中提供的容器,除此以外,Hashtable、Dictionary、BitSet、Stack、Properties都是遺留容器),已經不推薦使用,可是因爲ArrayList和LinkedListed都是非線程安全的,若是遇到多個線程操做同一個容器的場景,則能夠經過工具類Collections中的synchronizedList方法將其轉換成線程安全的容器後再使用(這是對裝潢模式的應用,將已有對象傳入另外一個類的構造器中建立新的對象來加強實現)。
44.Collection 和 Collections 的區別?
Collection是一個接口,它是Set、List等容器的父接口;Collections是個一個工具類,提供了一系列的靜態方法來輔助容器操做,這些方法包括對容器的搜索、排序、線程安全化等等。
45.List、Map、Set 三個接口存取元素時,各有什麼特色?
Collection 是一個接口,它是 Set、List 等容器的父接口;Collections 是個一個
工具類,提供了一系列的靜態方法來輔助容器操做,這些方法包括對容器的搜索、
排序、線程安全化等等。
46.Thread 類的 sleep()方法和對象的 wait()方法均可以讓線程暫停執行,它們有什麼區別?
sleep()方法(休眠)是線程類(Thread)的靜態方法,調用此方法會讓當前線程暫停執行指定的時間,將執行機會(CPU)讓給其餘線程,可是對象的鎖依然保持,所以休眠時間結束後會自動恢復(線程回到就緒狀態,請參考第66題中的線程狀態轉換圖)。
wait()是Object類的方法,調用對象的wait()方法致使當前線程放棄對象的鎖(線程暫停執行),進入對象的等待池(waitpool),只有調用對象的notify()方法(或notifyAll()方法)時才能喚醒等待池中的線程進入等鎖池(lockpool),若是線程從新得到對象的鎖就能夠進入就緒狀態。
47.線程的 sleep()方法和 yield()方法有什麼區別?
① sleep()方法給其餘線程運行機會時不考慮線程的優先級,所以會給低優先級的線程以運行的機會;yield()方法只會給相同優先級或更高優先級的線程以運行的機會;
② 線程執行 sleep()方法後轉入阻塞(blocked)狀態,而執行 yield()方法後轉入就緒(ready)狀態;
③ sleep()方法聲明拋出 InterruptedException,而 yield()方法沒有聲明任何異常;
④ sleep()方法比 yield()方法(跟操做系統 CPU 調度相關)具備更好的可移植性。
48.當一個線程進入一個對象的 synchronized 方法 A 以後,其它線程是否可進入此對象的 synchronized 方法 B?
不能。其它線程只能訪問該對象的非同步方法,同步方法則不能進入。由於非靜態方法上的synchronized修飾符要求執行方法時要得到對象的鎖,若是已經進入A方法說明對象鎖已經被取走,那麼試圖進入B方法的線程就只能在等鎖池(注意不是等待池哦)中等待對象的鎖。
49.請說出與線程同步以及線程調度相關的方法。
wait():使一個線程處於等待(阻塞)狀態,而且釋放所持有的對象的鎖;
sleep():使一個正在運行的線程處於睡眠狀態,是一個靜態方法,調用此方法要處理InterruptedException異常;
notify():喚醒一個處於等待狀態的線程,固然在調用此方法的時候,並不能確切的喚醒某一個等待狀態的線程,而是由JVM肯定喚醒哪一個線程,並且與優先級無關;
notityAll():喚醒全部處於等待狀態的線程,該方法並非將對象的鎖給全部線程,而是讓它們競爭,只有得到鎖的線程才能進入就緒狀態;
50.編寫多線程程序有幾種實現方式?
Java5之前實現多線程有兩種實現方法:
一種是繼承Thread類;
另外一種是實現Runnable接口。
兩種方式都要經過重寫run()方法來定義線程的行爲,推薦使用後者,由於Java中的繼承是單繼承,一個類有一個父類,若是繼承了Thread類就沒法再繼承其餘類了,顯然使用Runnable接口更爲靈活
51.synchronized 關鍵字的用法?
synchronized 關鍵字能夠將對象或者方法標記爲同步,以實現對對象和方法的互斥訪問,能夠用 synchronized(對象) { … }定義同步代碼塊,或者在聲明方法時將 synchronized 做爲方法的修飾符。在第 60 題的例子中已經展現了synchronized 關鍵字的用法。
52. 舉例說明同步和異步。
若是系統中存在臨界資源(資源數量少於競爭資源的線程數量的資源),例如正在寫的數據之後可能被另外一個線程讀到,或者正在讀的數據可能已經被另外一個線程寫過了,那麼這些數據就必須進行同步存取(數據庫操做中的排他鎖就是最好的例子)。當應用程序在對象上調用了一個須要花費很長時間來執行的方法,而且不但願讓程序等待方法的返回時,就應該使用異步編程,在不少狀況下采用異步途徑每每更有效率。事實上,所謂的同步就是指阻塞式操做,而異步就是非阻塞式操做
53. 啓動一個線程是調用 run()仍是 start()方法?
啓動一個線程是調用 start()方法,使線程所表明的虛擬處理機處於可運行狀態,這意味着它能夠由 JVM 調度並執行,這並不意味着線程就會當即運行。run()方法是線程啓動後要進行回調(callback)的方法。
54.簡述 synchronized java.util.concurrent.locks.Lock的異同?
Lock 是 Java 5 之後引入的新的 API,和關鍵字 synchronized 相比主要相同點:Lock 能完成 synchronized 所實現的全部功能;主要不一樣點:Lock 有比synchronized 更精確的線程語義和更好的性能,並且不強制性的要求必定要得到鎖。synchronized 會自動釋放鎖,而 Lock 必定要求程序員手工釋放,而且最好在 finally 塊中釋放(這是釋放外部資源的最好的地方)
55.Java 中如何實現序列化,有什麼意義?
序列化就是一種用來處理對象流的機制,所謂對象流也就是將對象的內容進行流化。能夠對流化後的對象進行讀寫操做,也可將流化後的對象傳輸於網絡之間。序列化是爲了解決對象流讀寫操做時可能引起的問題(若是不進行序列化可能會存在數據亂序的問題)。要實現序列化,須要讓一個類實現 Serializable 接口,該接口是一個標識性接口,標註該類對象是可被序列化的,而後使用一個輸出流來構造一個對象輸出流並經過 writeObject(Object)方法就能夠將實現對象寫出(即保存其狀態);若是須要反序列化則能夠用一個輸入流創建對象輸入流,而後經過 readObject 方法從流中讀取對象。序列化除了可以實現對象的持久化以外,還可以用於對象的深度克隆
56.Java 中有幾種類型的流?
字節流和字符流。字節流繼承於 InputStream、OutputStream,字符流繼承於Reader、Writer。在 java.io 包中還有許多其餘的流,主要是爲了提升性能和使用方便。關於 Java 的 I/O 須要注意的有兩點:一是兩種對稱性(輸入和輸出的對稱性,字節和字符的對稱性);二是兩種設計模式(適配器模式和裝潢模式)。另外 Java 中的流不一樣於 C#的是它只有一個維度一個方向
關於
關注公衆號「程序員小R」 回覆「666」 獲取全套面試題