Java面試題集錦(持續更新)
1、面向物件的特徵有哪些方面?
答:面向物件的特徵主要有以下幾個方面:
-抽象:抽象是將一類物件的共同特徵總結出來構造類的過程,包括資料抽象和行為抽象兩方面。抽象只關注物件有哪些屬性和行為,並不關注這些行為的細節是什麼。
-繼承:繼承是從己有類得到繼承資訊建立新類的過程。提供繼承資訊的類被稱為父類(超類、基類);得到繼承資訊的類被稱為子類(派生類)。繼承讓變化中的軟體系統有了一定的延續性,同時繼承也是封裝程式中可變因素的重要手段(如果不能理解請閱讀閻巨集博士的《Java與模式》或《設計模式精解》中關於橋樑模式的部分)。
-封裝:通常認為封裝是把資料和操作資料的方法繫結起來,對資料的訪問只能通過己定義的介面。面向物件的本質就是將現實世界描繪成一系列完全自治、封閉的物件。我們在類中編寫的方法就是對實現細節的一種封裝;我們編寫一個類就是對資料和資料操作的封裝。可以說,封裝就是隱藏一切可隱藏的東西,只向外界提供最簡單的程式設計介面(可以想想普通洗衣機和全自動洗衣機的差別,明顯全自動洗衣機封裝更好因此操作起來更簡單;我們現在使用的智慧手機也是封裝得足夠好的,因為幾個按鍵就搞定了所有的事情)。
-多型性:多型性是指允許不同子型別的物件對同一訊息作出不同的響應。簡單的說就是用同樣的物件引用呼叫同樣的方法但是做了不同的事情。多型性分為編譯時的多型性和執行時的多型性。如果將物件的方法視為物件向外界提供的服務,那麼執行時的多型性可以解釋為:當A系統訪問B系統提供的服務時,B系統有多種提供服務的方式,但一切對A系統來說都是透明的(就像電動剃鬚刀是A系統,它的供電系統是B系統,B系統可以使用電池供電或者用交流電,甚至還有可能是太陽能,A系統只會通過B類物件呼叫供電的方法,但並不知道供電系統的底層實現是什麼,究竟通過何種方式獲得了動力)。方法過載(overload)實現的是編譯時的多型性(也稱為前繫結),而方法重寫(override)實現的是執行時的多型性(也稱為後繫結)。執行時的多型是面向物件最精髓的東西,要實現多型需要做兩件事:1).方法重寫(子類繼承父類並重寫父類中己有的或抽象的方法);2).物件造型(用父型別引用引用子型別物件,這樣同樣的引用呼叫同樣的方法就會根據子類物件的不同而表現出不同的行為)。
2、 解釋記憶體中的棧(stack)、堆(heap)和方法區(method area)的用法。
答:通常我們定義一個基本資料型別的變數,一個物件的引用,還有就是函式呼叫的現場儲存都使用JVM中的棧空間;而通過new關鍵字和構造器建立的物件則放在堆空間,堆是垃圾收集器管理的主要區域,由於現在的垃圾收集器都採用分代收集演算法,所以堆空間還可以細分為新生代和老生代,再具體一點可以分為 Eden、Survivor (又可分為 From Survivor 和 To Survivor)、Tenured;方法區和堆都是各個執行緒共享的記憶體區域,用於儲存己經被JVM載入的類資訊、常量、靜態變數、JIT編譯器編譯後的程式碼等資料;程式中的字面量(literal)如直接書寫的100、"hello"和常量都是放在常量池中,常量池是方法區的一部分,棧空間操作起來最快但是棧很小,通常大量的物件都是放在堆空間,棧和
上面的語句中變數str放在棧上,用new創建出來的字串物件放在堆上,而"hello"這個字面量是放在方法區的。
3 、陣列有沒有 length()方法?String 有沒有 length() 方法?
答:陣列沒有 length()方法,有 length 的屬性。String 有 length()方法。JavaScript 中,獲得字串的長度是通過 length 屬性得到的,這一點容易和Java 混淆。
4 、兩個物件值相同 (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 註解。
6、過載( Overload )和重寫( Override )的區別。過載的方法能否根據返回型別進行區分?
答:方法的過載和重寫都是實現多型的方式,區別在於前者實現的是編譯時的多型性,而後者實現的是執行時的多型性。過載發生在一個類中,同名的方法如果有不同的引數列表(引數型別不同、引數個數不同或者二者都不同)則視為過載;重寫發生在子類與父類之間,重寫要求子類被重寫方法與父類被重寫方法有相同的返回型別,比父類被重寫方法更好訪問,不能比父類被重寫方法宣告更多的異常(里氏代換原則)。過載對返回型別沒有特殊的要求。 面試題:華為的面試題中曾經問過這樣一個問題 - "為什麼不能根據返回型別來區分過載",快說出你的答案吧!