1. 程式人生 > >Java 面向物件 面試題

Java 面向物件 面試題

1、封裝具有的特性?

答:(1)在類的定義中設定訪問物件屬性(資料成員)及方法(成員方法)的許可權,限制本類物件及其他類的物件使用的範圍。

(2)提供一個介面來描述其他物件的使用方法

(3)其他物件不能直接修改本物件所擁有的屬性和方法

(4)封裝反映了事物的相對獨立性

 (5)封裝在程式設計上的作用是使物件以外的部分不能隨意存取物件的內部資料(屬性),從而有效地避免了外部錯誤對它的“交叉感染”。

(6)當物件的內部做了某些修改時,由於它只通過少量的介面對外提供服務,因此大大減少了內部的修改對外部的影響。

(7)面向物件系統的封裝單位是物件,類概念本身也具有封裝的意義,因為物件的特性是由它所屬的類說明來描述的。

2、什麼時候應用帶參建構函式?

當需要對物件進行一次性的初始化時,可使用帶參的建構函式。

父類擁有帶參的構造時,子類繼承父類,子類需編寫帶引數建構函式,並呼叫父類建構函式

3、內部類的二個好處是?

內部類的第一個好處是——隱藏你不想讓別人知道的操作,也即封裝性。

內部類的第二個好處誰——每一個內部類物件可以訪問建立它的外部類物件的內容,甚至包括私有變數!

4、內部類的作用?

1.內部類可以很好的實現隱藏

  一般的非內部類,是不允許有private 與protected許可權的,但內部類可以

2.內部類擁有外圍類的所有元素的訪問許可權

3.可是實現多重繼承

4.可以避免修改介面而實現同一個類中兩種同名方法的呼叫。

5、在Java中,子類可以從父類中繼承哪些?

答:(1)繼承public和protected修飾的屬性和方法,不管子類和父類是否在同一個包裡。

(2)繼成預設許可權修飾符修飾的屬性和方法,但子類和父類必須在同一個包裡。

(3)無法繼承private修飾的屬性和方法。

(4)無法繼承父類的構造方法。

6、方法過載與重寫的區別?

答:過載(Overloading)

    (1)   方法過載是讓類以統一的方式處理不同型別資料的一種手段。多個同名函式同時存在,具有不同的引數個數/型別。過載Overloading是一個類中多型性的一種表現。

     (2)   Java的方法過載,就是在類中可以建立多個方法,它們具有相同的名字,但具有不同的引數和不同的定義。呼叫方法時通過傳遞給它們的不同引數個數和引數型別來決定具體使用哪個方法, 這就是多型性。

     (3)   過載的時候,方法名要一樣,但是引數型別和個數不一樣,返回值型別可以相同也可以不相同。無法以返回型別作為過載函式的區分標準。

重寫(Overriding)

(1)父類與子類之間的多型性,對父類的函式進行重新定義。如果在子類中定義某方法與其父類有相同的名稱和引數,我們說該方法被重寫 (Overriding)。在Java中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。但有時子類並不想原封不動地繼承父類的方法,而是想作一定的修改,這就需要採用方法的重寫。方法重寫又稱方法覆蓋。

  (2)若子類中的方法與父類中的某一方法具有相同的方法名、返回型別和引數表,則新方法將覆蓋原有的方法。如需父類中原有的方法,可使用super關鍵字,該關鍵字引用了當前類的父類。

  (3)子類函式的訪問修飾許可權不能少於父類的;

7、Java中的抽象類和介面的區別?

  1)抽象類在 Java 語言中表示的是一種繼承關係,一個類只能使用一次繼承關係。但是,一個類卻可以實現多個介面。

  2)在抽象類中可以有自己的資料成員,也可以有非抽象的成員方法,而在介面中,只能夠有靜態的不能被修改的資料成員(也就是必須是static final的,不過在介面中一般不定義資料成員,介面中只能定義常量),所有的成員方法都是抽象的。

  3) 抽象類和介面所反映出的設計理念不同。其實抽象類表示的是"is-a"關係,介面表示的是"like-a"關係。

  4)實現抽象類和介面的類必須實現其中的所有方法。抽象類中可以有非抽象方法。介面中則不能有實現方法。

  5)介面中定義的變數預設是publicstatic final 型,且必須給其初值,所以實現類中不能重新定義,也不能改變其值。

  6)抽象類中的變數預設是friendly 訪問級別,其值可以在子類中重新定義,也可以重新賦值。

  7)介面中的方法預設都是public, abstract 型別的。

8、介面隔離原則和單一原則如何理解

  單一是指介面要儘量的智慧單一,不要造成為了實現一個介面,而被迫實現不需要的方法的情況。隔離的是實現和呼叫,這樣才能真正解決團隊的並行開發問題

9、如果不使用try-catch,程式出現異常會如何?

解答:將按照下面的步驟處理:

(1)虛擬機器列印異常資訊。

(2)程式終止。

越早處理異常消耗的資源和時間越小,產生影響的範圍也越小。因此,不要把自己能處理的異常也拋給呼叫者。

10、finally在什麼時候使用?

解答:finally語句塊是在任何情況下都會執行的程式碼,這樣可以保證一些在任何情況下都必須執行程式碼的可靠性。比如,在資料庫查詢異常的時候,應該釋放資料庫連線等等。finally語句先於return語句執行,而不論其先後位置,也不管是否try塊出現異常。finally 語句唯一不被執行的情況是方法執行了System.exit()方法。System.exit()的作用是終止當前正在執行的 Java 虛擬機器。建議不要在finally塊中使用return語句,沒有意義還容易導致錯誤。

11、throw和throws關鍵字的區別?

解答:throw用來丟擲一個異常,在方法體內。語法格式為:throw 異常物件。 throws用來宣告方法可能會丟擲什麼異常,在方法名後,語法格式為:

throws 異常型別1,異常型別2...異常型別n。

12. String和StringBuffer區別

答:JAVA平臺提供了兩個類:String和StringBuffer,它們可以儲存和操作字串,即包含多個字元的字元資料。這個String類提供了數值不可改變的字串。而這個StringBuffer類提供的字串進行修改。當你知道字元資料要改變的時候你就可以使用StringBuffer。典型地,你可以使用StringBuffers來動態構造字元資料。

13. 異常的兩種型別,Error和Exception的區別

答:error 表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說記憶體溢位。不可能指望程式能處理這樣的情況。

exception 表示一種設計或實現問題。也就是說,它表示如果程式執行正常,從不會發生的情況。

14. 談談final, finally, finalize的區別

答:final—修飾符(關鍵字)如果一個類被宣告為final,意味著它不能再派生出新的子類,不能作為父類被繼承。

   因此一個類不能既被宣告為abstract的,又被宣告為final的。將變數或方法宣告為final,可以保證它們在使用中不被改變。

   被宣告為final的變數必須在宣告時給定初值,而在以後的引用中只能讀取,不可修改。被宣告為final的方法也同樣只能使用,

   不能過載finally—再異常處理時提供finally 塊來執行任何清除操作。如果丟擲一個異常,那麼相匹配的 catch 子句就會執行,

   然後控制就會進入finally 塊(如果有的話)finalize—方法名。Java 技術允許使用 finalize() 方法在垃圾收集器將物件從

   記憶體中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在確定這個物件沒有被引用時對這個物件呼叫的。

   它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統資源或者執行其他清理工作。

  finalize() 方法是在垃圾收集器刪除物件之前對這個物件呼叫的.

15. 面向物件的特徵有哪些方面?

答:主要有以下四方面:
1.抽象:抽象就是忽略一個主題中與當前目標無關的那些方面,以便更充分地注意與當前目標有關的方面。

    抽象並不打算了解全部問題,而只是選擇其中的一部分,暫時不用部分細節。抽象包括兩個方面,一是過程抽象,二是資料抽象。

 2.繼承:繼承是一種聯結類的層次模型,並且允許和鼓勵類的重用,它提供了一種明確表述共性的方法。

    物件的一個新類可以從現有的類中派生,這個過程稱為類繼承。新類繼承了原始類的特性,新類稱為原始類的派生類(子類),

    而原始類稱為新類的基類(父類)。派生類可以從它的基類那裡繼承方法和例項變數,並且類可以修改或增加新的方法使之更

    適合特殊的需要。

3.封裝:封裝是把過程和資料包圍起來,對資料的訪問只能通過已定義的介面。面向物件計算始於這個基本概念,

    即現實世界可以被描繪成一系列完全自治、封裝的物件,這些物件通過一個受保護的介面訪問其他物件。

4.多型性:多型性是指允許不同類的物件對同一訊息作出響應。多型性包括引數化多型性和包含多型性。

多型性語言具有靈活、抽象、行為共享、程式碼共享的優勢,很好的解決了應用程式函式同名問題。

16. int 和?Integer 有什麼區別

答:Java 提供兩種不同的型別:引用型別和原始型別(或內建型別)。Int是java的原始資料型別,Integer是java為int提供的封裝類。

   Java為每個原始型別提供了封裝類。原始型別封裝類,booleanBoolean,charCharacter,byteByte,shortShort,intInteger,

   longLong,floatFloat,doubleDouble引用型別和原始型別的行為完全不同,並且它們具有不同的語義。引用型別和原始型別具有不同的

    特徵和用法,它們包括:大小和速度問題,這種型別以哪種型別的資料結構儲存,當引用型別和原始型別用作某個類的例項資料時所指定的

預設值。物件引用例項變數的預設值為?null,而原始型別例項變數的預設值與它們的型別有關.

17. JAVA語言如何進行異常處理,關鍵字:throws,throw,try,catch,finally分別代表什麼意義?在try塊中可以丟擲異常嗎?

答:Java通過面向物件的方法進行異常處理,把各種不同的異常進行分類,並提供了良好的介面。在Java中,每個異常都是一個物件,

    它是Throwable類或其它子類的例項。當一個方法出現異常後便丟擲一個異常物件,該物件中包含有異常資訊,呼叫這個物件的

    方法可以捕獲到這個異常並進行處理。Java的異常處理是通過5個關鍵詞來實現的:try、catch、throw、throws和finally。

    一般情況下是用try來執行一段程式,如果出現異常,系統會丟擲(throws)一個異常,這時候你可以通過它的型別來捕捉(catch)

    它,或最後(finally)由預設處理器來處理。用try來指定一塊預防所有"異常"的程式。緊跟在try程式後面,應包含一個catch子

    句來指定你想要捕捉的"異常"的型別。throw語句用來明確地丟擲一個"異常"。throws用來標明一個成員函式可能丟擲的各種"異常"。

   Finally為確保一段程式碼不管發生什麼"異常"都被執行一段程式碼。可以在一個成員函式呼叫的外面寫一個try語句,在這個成員函式

    內部寫另一個try語句保護其他程式碼。每當遇到一個try語句,"異常"的框架就放到堆疊上面,直到所有的try語句都完成。

如果下一級的try語句沒有對某種"異常"進行處理,堆疊就會展開,直到遇到有處理這種"異常"的try語句。

18. java中有幾種方法可以實現一個執行緒?用什麼關鍵字修飾同步方法?stop()和suspend()方法為何不推薦使用?

答:有兩種實現方法,分別是繼承Thread類與實現Runnable介面用synchronized關鍵字修飾同步方法反對使用stop(),是因為它不安全。它會解除由執行緒獲取的所有鎖定,而且如果物件處於一種不連貫狀態,那麼其他執行緒能在那種狀態下檢查和修改它們。結果很難檢查出真正的問題所在。suspend()方法容易發生死鎖。呼叫suspend()的時候,目標執行緒會停下來,但卻仍然持有在這之前獲得的鎖定。此時,其他任何執行緒都不能訪問鎖定的資源,除非被"掛起"的執行緒恢復執行。對任何執行緒來說,如果它們想恢復目標執行緒,同時又試圖使用任何一個鎖定的資源,就會造成死鎖。所以不應該使用suspend(),而應在自己的Thread類中置入一個標誌,指出執行緒應該活動還是掛起。若標誌指出執行緒應該掛起,便用wait()命其進入等待狀態。若標誌指出執行緒應當恢復,則用一個notify()重新啟動執行緒。

19. sleep()和wait()有什麼區別??

答:sleep是執行緒類(Thread)的方法,導致此執行緒暫停執行指定時間,給執行機會給其他執行緒,但是監控狀態依然保持,到時後會自動恢復。呼叫sleep不會釋放物件鎖。wait是Object類的方法,對此物件呼叫wait方法導致本執行緒放棄物件鎖,進入等待此物件的等待鎖定池,只有針對此物件發出notify方法(或notifyAll)後本執行緒才進入物件鎖定池準備獲得物件鎖進入執行狀態。

20. 同步和非同步有何異同,在什麼情況下分別使用他們?舉例說明。

答:如果資料將線上程間共享。例如正在寫的資料以後可能被另一個執行緒讀到,或者正在讀的資料可能已經被另一個執行緒寫過了,那麼這些資料就是共享資料,必須進行同步存取。當應用程式在物件上呼叫了一個需要花費很長時間來執行的方法,並且不希望讓程式等待方法的返回時,就應該使用非同步程式設計,在很多情況下采用非同步途徑往往更有效率。

21. 使用final關鍵字修飾一個變數時,是引用不能變,還是引用的物件不能變?

使用final關鍵字修飾一個變數時,是指引用變數不能變,引用變數所指向的物件中的內容還是可以改變的。例如,對於如下語句:

 final StringBuffer a=newStringBuffer("immutable");

執行如下語句將報告編譯期錯誤:

a=new StringBuffer("");

但是,執行如下語句則可以通過編譯:

a.append(" broken!");

有人在定義方法的引數時,可能想採用如下形式來阻止方法內部修改傳進來的引數物件:

         publicvoid method(final  StringBuffer  param)

         {

         }

實際上,這是辦不到的,在該方法內部仍然可以增加如下程式碼來修改引數物件:

                   param.append("a");

22. "=="和equals方法究竟有什麼區別?

(單獨把一個東西說清楚,然後再說清楚另一個,這樣,它們的區別自然就出來了,混在一起說,則很難說清楚)

==操作符專門用來比較兩個變數的值是否相等,也就是用於比較變數所對應的記憶體中所儲存的數值是否相同,要比較兩個基本型別的資料或兩個引用變數是否相等,只能用==操作符。

如果一個變數指向的資料是物件型別的,那麼,這時候涉及了兩塊記憶體,物件本身佔用一塊記憶體(堆記憶體),變數也佔用一塊記憶體,例如Objet obj = new Object();變數obj是一個記憶體,newObject()是另一個記憶體,此時,變數obj所對應的記憶體中儲存的數值就是物件佔用的那塊記憶體的首地址。對於指向物件型別的變數,如果要比較兩個變數是否指向同一個物件,即要看這兩個變數所對應的記憶體中的數值是否相等,這時候就需要用==操作符進行比較。

equals方法是用於比較兩個獨立物件的內容是否相同,就好比去比較兩個人的長相是否相同,它比較的兩個物件是獨立的。例如,對於下面的程式碼:

String a=new String("foo");

String b=new String("foo");

兩條new語句建立了兩個物件,然後用a,b這兩個變數分別指向了其中一個物件,這是兩個不同的物件,它們的首地址是不同的,即a和b中儲存的數值是不相同的,所以,表示式a==b將返回false,而這兩個物件中的內容是相同的,所以,表示式a.equals(b)將返回true。

在實際開發中,我們經常要比較傳遞進行來的字串內容是否等,例如,String input = …;input.equals(“quit”),許多人稍不注意就使用==進行比較了,這是錯誤的,隨便從網上找幾個專案實戰的教學視訊看看,裡面就有大量這樣的錯誤。記住,字串的比較基本上都是使用equals方法。

如果一個類沒有自己定義equals方法,那麼它將繼承Object類的equals方法,Object類的equals方法的實現程式碼如下:

boolean equals(Object o){

return this==o;

}

這說明,如果一個類沒有自己定義equals方法,它預設的equals方法(從Object 類繼承的)就是使用==操作符,也是在比較兩個變數指向的物件是否是同一物件,這時候使用equals和使用==會得到同樣的結果,如果比較的是兩個獨立的物件則總返回false。如果你編寫的類希望能夠比較該類建立的兩個例項物件的內容是否相同,那麼你必須覆蓋equals方法,由你自己寫程式碼來決定在什麼情況即可認為兩個物件的內容是相同的。

23. 靜態變數和例項變數的區別?

在語法定義上的區別:靜態變數前要加static關鍵字,而例項變數前則不加。

在程式執行時的區別:例項變數屬於某個物件的屬性,必須建立了例項物件,其中的例項變數才會被分配空間,才能使用這個例項變數。靜態變數不屬於某個例項物件,而是屬於類,所以也稱為類變數,只要程式載入了類的位元組碼,不用建立任何例項物件,靜態變數就會被分配空間,靜態變數就可以被使用了。總之,例項變數必須建立物件後才可以通過這個物件來使用,靜態變數則可以直接使用類名來引用。

例如,對於下面的程式,無論建立多少個例項物件,永遠都只分配了一個staticVar變數,並且每建立一個例項物件,這個staticVar就會加1;但是,每建立一個例項物件,就會分配一個instanceVar,即可能分配多個instanceVar,並且每個instanceVar的值都只自加了1次。

public class VariantTest

{

                   publicstatic int staticVar = 0;

                   publicint instanceVar = 0;

                   publicVariantTest()

                   {

                            staticVar++;

                            instanceVar++;

                            System.out.println(“staticVar=”+ staticVar + ”,instanceVar=” + instanceVar);

                   }

}

備註:這個解答除了說清楚兩者的區別外,最後還用一個具體的應用例子來說明兩者的差異,體現了自己有很好的解說問題和設計案例的能力,思維敏捷,超過一般程式設計師,有寫作能力!

24. Math.round(11.5)等於多少?Math.round(-11.5)等於多少?

Math類中提供了三個與取整有關的方法:ceil、floor、round,這些方法的作用與它們的英文名稱的含義相對應,例如,ceil的英文意義是天花板,該方法就表示向上取整,所以,Math.ceil(11.3)的結果為12,Math.ceil(-11.3)的結果是-11;floor的英文意義是地板,該方法就表示向下取整,所以,Math.floor(11.6)的結果為11,Math.floor(-11.6)的結果是-12;最難掌握的是round方法,它表示“四捨五入”,演算法為Math.floor(x+0.5),即將原來的數字加上0.5後再向下取整,所以,Math.round(11.5)的結果為12,Math.round(-11.5)的結果為-11。

25. 幾種常用的資料結構及內部實現原理?

 連結串列:一個連結串列由很多節點組成,每個節點包含表示內容的資料域和指向下一個節點的鏈域兩部分。正是通過鏈域將節點連線形成一個表。圍繞連結串列的基本操作有新增節點、刪除節點和查詢節點等。

 堆疊:限定了只能從線性表的一端進行資料的存取,這一端稱為棧頂,另一端為棧底。入棧操作是先向棧頂方向移動一位,存入資料;出棧操作則是取出棧頂資料,然後向棧底移動一位。體現LIFO/FILO的思想。

 佇列:限定了資料只能從線性表的一端存入,從另一端取出。存入一端成為隊尾,取出一端稱為隊首。體現LILO/FIFO的思想。

 二叉樹:樹中的每個節點最多有兩個子節點。這兩個子節點分別稱為左子節點和右子節點。在建立二叉搜尋樹時,要求一個節點的左子節點的關鍵字值小於這個節點而右子節點的關鍵字值大於或等於這個節點。常見的遍歷操作有前序、中序和後序遍歷。