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的思想。

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

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章