【前言】別人都在你看不到的地方暗自努力,在你看獲得的地方,他們也和你同樣顯得不務正業,和你同樣會抱怨,而只有你本身相信這些都是真的,最後,也只有你一我的繼續不思進取 …… java
【下載】本人剛學習Java時總結的一些JavaSE常見面試題,偶爾在電腦中翻出,從新整理一下分享給須要的人,主要針對初級程序員。想要PDF完整版下載的,評論裏留言留下你的郵箱!程序員
21.在Java中,如何跳出當前的多重嵌套循環? 面試
答:在最外層循環前加一個標記如A,而後用break A;能夠跳出多重循環。(Java中支持帶標籤的break和continue語句,做用有點相似於C和C++中的goto語句,可是就像要避免使用goto同樣,應該避免使用帶標籤的break和continue,由於它不會讓你的程序變得更優雅,不少時候甚至有相反的做用,因此這種語法其實不知道更好)編程
22.構造器(constructor)是否可被重寫(override)? 設計模式
答:構造器不能被繼承,所以不能被重寫,但能夠被重載。數組
23.兩個對象值相同(x.equals(y) == true),但卻可有不一樣的hash code,這句話對不對? 緩存
答:不對,若是兩個對象x和y知足x.equals(y) == true,它們的哈希碼(hash code)應當相同。Java對於eqauls方法和hashCode方法是這樣規定的:安全
(1)若是兩個對象相同(equals方法返回true),那麼它們的hashCode值必定要相同;服務器
(2)若是兩個對象的hashCode相同,它們並不必定相同。多線程
固然,你未必要按照要求去作,可是若是你違背了上述原則就會發如今使用容器時,相同的對象能夠出如今Set集合中,同時增長新元素的效率會大大降低(對於使用哈希存儲的系統,若是哈希碼頻繁的衝突將會形成存取性能急劇降低)。
補充:關於equals和hashCode方法,不少Java程序都知道,但不少人也就是僅僅知道而已,在Joshua Bloch的大做《Effective Java》(不少軟件公司,《Effective Java》、《Java編程思想》以及《重構:改善既有代碼質量》是Java程序員必看書籍,若是你還沒看過,那就趕忙去亞馬遜買一本吧)中是這樣介紹equals方法的:首先equals方法必須知足自反性(x.equals(x)必須返回true)、對稱性(x.equals(y)返回true時,y.equals(x)也必須返回true)、傳遞性(x.equals(y)和y.equals(z)都返回true時,x.equals(z)也必須返回true)和一致性(當x和y引用的對象信息沒有被修改時,屢次調用x.equals(y)應該獲得一樣的返回值),並且對於任何非null值的引用x,x.equals(null)必須返回false。實現高質量的equals方法的訣竅包括:1.使用==操做符檢查"參數是否爲這個對象的引用";2.使用instanceof操做符檢查"參數是否爲正確的類型";3.對於類中的關鍵屬性,檢查參數傳入對象的屬性是否與之相匹配;4.編寫完equals方法後,問本身它是否知足對稱性、傳遞性、一致性;5.重寫equals時老是要重寫hashCode;6.不要將equals方法參數中的Object對象替換爲其餘的類型,在重寫時不要忘掉@Override註解。
24.是否能夠繼承String類?
答:String 類是final類,不能夠被繼承。
補充:繼承String自己就是一個錯誤的行爲,對String類型最好的重用方式是關聯關係(Has-A)和依賴關係(Use-A)而不是繼承關係(Is-A)。
25.當一個對象被看成參數傳遞到一個方法後,此方法可改變這個對象的屬性,並可返回變化後的結果,那麼這裏究竟是值傳遞仍是引用傳遞?
答:是值傳遞。Java語言的方法調用只支持參數的值傳遞。當一個對象實例做爲一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的屬性能夠在被調用過程當中被改變,但對對象引用的改變是不會影響到調用者的。C++和C#中能夠經過傳引用或傳輸出參數來改變傳入的參數的值。在C#中能夠編寫以下所示的代碼,可是在Java中卻作不到。
namespace CS01 {
class Program {
public static void swap(ref int x, ref int y) {
int temp = x;
x = y;
y = temp;
}
public static void Main (string[] args) {
int a = 5, b = 10;
swap (ref a, ref b);
// a = 10, b = 5;
Console.WriteLine ("a = {0}, b = {1}", a, b);
}
}
}
說明:Java中沒有傳引用實在是很是的不方便,這一點在Java 8中仍然沒有獲得改進,正是如此在Java編寫的代碼中才會出現大量的Wrapper類(將須要經過方法調用修改的引用置於一個Wrapper類中,再將Wrapper對象傳入方法),這樣的作法只會讓代碼變得臃腫,尤爲是讓從C和C++轉型爲Java程序員的開發者沒法容忍。
26.String和StringBuilder、StringBuffer的區別?
答:(1)String和StringBuffer、StringBuider:
①String:是不可變字符序列;
②StringBuffer、StringBuider:是可變字符序列;
③String覆蓋了equals方法和hashCode方法,而StringBuffer沒有覆蓋equals方法和hashCode方法,因此,將StringBuffer對象存儲進Java集合類中時會出現問題。
(2)StringBuffer和StringBuider:
①StringBuffer:是JDK1.0版本的,線程安全,效率低;
②StringBuilder:是JDK1.5版本的,線程不安全,效率高;
③若是一個字符串變量是在方法裏面定義,這種狀況只可能有一個線程訪問它,不存在不安全的因素了,則用StringBuilder。若是要在類裏面定義成員變量,而且這個類的實例對象會在多線程環境下使用,那麼最好用StringBuffer。
27.描述一下JVM加載class文件的原理機制?
答:JVM中類的裝載是由類加載器(ClassLoader)和它的子類來實現的,Java中的類加載器是一個重要的Java運行時系統組件,它負責在運行時查找和裝入類文件中的類。
因爲Java的跨平臺性,通過編譯的Java源程序並非一個可執行程序,而是一個或多個類文件。當Java程序須要使用某個類時,JVM會確保這個類已經被加載、鏈接(驗證、準備和解析)和初始化。類的加載是指把類的.class文件中的數據讀入到內存中,一般是建立一個字節數組讀入.class文件,而後產生與所加載類對應的Class對象。加載完成後,Class對象還不完整,因此此時的類還不可用。當類被加載後就進入鏈接階段,這一階段包括驗證、準備(爲靜態變量分配內存並設置默認的初始值)和解析(將符號引用替換爲直接引用)三個步驟。最後JVM對類進行初始化,包括:1)若是類存在直接的父類而且這個類尚未被初始化,那麼就先初始化父類;2)若是類中存在初始化語句,就依次執行這些初始化語句。
類的加載是由類加載器完成的,類加載器包括:根加載器(BootStrap)、擴展加載器(Extension)、系統加載器(System)和用戶自定義類加載器(java.lang.ClassLoader的子類)。從Java 2(JDK 1.2)開始,類加載過程採起了父親委託機制(PDM)。PDM更好的保證了Java平臺的安全性,在該機制中,JVM自帶的Bootstrap是根加載器,其餘的加載器都有且僅有一個父類加載器。類的加載首先請求父類加載器加載,父類加載器無能爲力時才由其子類加載器自行加載。JVM不會向Java程序提供對Bootstrap的引用。下面是關於幾個類加載器的說明:
Bootstrap:通常用本地代碼實現,負責加載JVM基礎核心類庫(rt.jar);
Extension:從java.ext.dirs系統屬性所指定的目錄中加載類庫,它的父加載器是Bootstrap;
System:又叫應用類加載器,其父類是Extension。它是應用最普遍的類加載器。它從環境變量classpath或者系統屬性java.class.path所指定的目錄中記載類,是用戶自定義加載器的默認父加載器。
28.抽象類(abstract class)和接口(interface)有什麼異同?
答:(1)成員特色:
①構造方法:接口沒有;抽象類有;
②成員變量:接口中只有常量;抽象類中常量、變量均可;
③成員方法:接口只有抽象方法;抽象類中抽象方法、非抽象方法均可;
(2)關係特色:
①類與類:只有單繼承,但能夠多層繼承;
②類與接口:實現關係,能夠單實現,也能夠多實現;
③接口與接口:繼承關係,能夠單繼承,也能夠多繼承;
(3)設計理念:
①接口是簡單工廠設計模式,like a的關係 ,接口中定義的是該繼承體系的擴展功能;
③抽象類是模板設計模式,is a的關係,抽象類中定義的是繼承體系的共性功能;
29.Java中會存在內存泄漏嗎,請簡單描述?
答:理論上Java由於有垃圾回收機制(GC)不會存在內存泄露問題(這也是Java被普遍使用於服務器端編程的一個重要緣由);然而在實際開發中,可能會存在無用但可達的對象,這些對象不能被GC回收,所以也會致使內存泄露的發生。例如Hibernate的Session(一級緩存)中的對象屬於持久態,垃圾回收器是不會回收這些對象的,然而這些對象中可能存在無用的垃圾對象,若是不及時關閉(close)或清空(flush)一級緩存就可能致使內存泄露。
30.抽象的(abstract)方法是否可同時是靜態的(static),是否可同時是本地方法(native),是否可同時被synchronized修飾?
答:都不能。抽象方法須要子類重寫,而靜態的方法是沒法被重寫的,所以兩者是矛盾的。本地方法是由本地代碼(如C代碼)實現的方法,而抽象方法是沒有實現的,也是矛盾的。synchronized和方法的實現細節有關,抽象方法不涉及實現細節,所以也是相互矛盾的。
31.是否能夠從一個靜態(static)方法內部發出對非靜態(non-static)方法的調用?
答:不能夠,靜態方法只能訪問靜態成員,由於非靜態方法的調用要先建立對象,在調用靜態方法時可能對象並無被初始化。
32.GC是什麼?爲何要有GC?
答:GC是垃圾收集的意思,Java提供的GC功能能夠自動監測對象是否超過做用域從而達到自動回收內存的目的,從而有效的防止內存泄露。要請求垃圾收集,能夠調用下面的方法之一:System.gc()或Runtime.getRuntime().gc(),但JVM能夠屏蔽掉顯示的垃圾回收調用。
33.String st = null和 String st =「 」的區別?String s = new String("xyz")建立了幾個對象?
答:(1)String st = null表示聲明瞭一個String對象的引用str,可是沒有爲其分配存內存空間。
(2)String st =「 」表示建立了一個長度等於0的空字符串,並在內存中分配了內存空間。
(3)String st = new String(「xyz」);表示建立了兩個對象:
①堆內存中一個new String;
②常量池中一個字符串。
34.接口是否可繼承(extends)接口?抽象類是否可實現(implements)接口?抽象類是否可繼承具體類(concrete class)?
答:接口能夠繼承接口,並且支持多重繼承。抽象類能夠實現(implements)接口,抽象類可繼承具體類也能夠繼承抽象類。
35.Anonymous Inner Class(匿名內部類)是否能夠繼承其它類?是否能夠實現接口?
答:能夠繼承其餘類或實現其餘接口,在Swing編程和Android開發中經常使用此方式來實現事件監聽和回調。
36.內部類能夠引用它的包含類(外部類)的成員嗎?有沒有什麼限制?
答:一個內部類對象能夠訪問建立它的外部類對象的成員,包括私有成員。
37.final、finally和finalized的區別?
答:(1)final:被final修飾的類,不被能繼承;被final修飾的方法,不能被重寫;被fianl修飾的量,爲常量,只能被賦值一次;
(2)finally:異常處理,和try、catch結合使用,可加可不加,用於執行一些必須執行的代碼,如釋放資源等;
(3)finalized:Object類中的方法,其中定義了對象要被垃圾回收器回收以前,要作的一些清理工做。
38.數據類型之間的轉換?
答:(1)如何將字符串轉換爲基本數據類型?
調用基本數據類型對應的包裝類中的方法parseXXX(String)或valueOf(String)便可返回相應基本類型;
(2)如何將基本數據類型轉換爲字符串?
一種方法是將基本數據類型與空字符串("")鏈接(+)便可得到其所對應的字符串;另外一種方法是調用String類中的valueOf()方法返回相應字符串
39.如何實現字符串的反轉及替換?
答:方法不少,能夠本身寫實現也可使用String或StringBuffer/StringBuilder中的方法。有一道很常見的面試題是用遞歸實現字符串反轉,代碼以下所示:
public static String reverse(String originStr) {
if(originStr == null || originStr.length() <= 1)
return originStr;
return reverse(originStr.substring(1)) + originStr.charAt(0);
}
40.怎樣將GB2312編碼的字符串轉換爲ISO-8859-1編碼的字符串?
答:代碼以下所示:
String s1 = "你好";
String s2 = new String(s1.getBytes("GB2312"), "ISO-8859-1");