JAVA開發面試題&基礎篇&第五部分

zsk1996888發表於2020-11-12

47.說明記憶體洩漏和記憶體溢位的區別和聯絡,結合專案經驗描述Java程式中如何檢測?如何解決?

答:記憶體溢位 out of memory,是指程式在申請記憶體時,沒有足夠的記憶體空間供其使用,出現out of memory;比如申請了一個integer,但給它存了long才能存下的數,那就是記憶體溢位。
記憶體洩露 memory leak,是指程式在申請記憶體後,無法釋放已申請的記憶體空間,一次記憶體洩露危害可以忽略,但記憶體洩露堆積後果很嚴重,無論多少記憶體,遲早會被佔光。
memory leak會最終會導致out of memory!

48.什麼是Java的序列化,如何實現Java的序列化?列舉在哪些程式中見過Java序列化?

答:Java中的序列化機制能夠將一個例項物件(只序列化物件的屬性值,而不會去序列化什麼所謂的方法。)的狀態資訊寫入到一個位元組流中使其可以通過socket進行傳輸、或者持久化到儲存資料庫或檔案系統中;然後在需要的時候通過位元組流中的資訊來重構一個相同的物件。一般而言,要使得一個類可以序列化,只需簡單實現java.io.Serializable介面即可。
物件的序列化主要有兩種用途:
1) 把物件的位元組序列永久地儲存到硬碟上,通常存放在一個檔案中;
2) 在網路上傳送物件的位元組序列。
在很多應用中,需要對某些物件進行序列化,讓它們離開記憶體空間,入住物理硬碟,以便長期儲存。比如最常見的是Web伺服器中的Session物件,當有 10萬使用者併發訪問,就有可能出現10萬個Session物件,記憶體可能吃不消,於是Web容器就會把一些seesion先序列化到硬碟中,等要用了,再把儲存在硬碟中的物件還原到記憶體中。
當兩個程式在進行遠端通訊時,彼此可以傳送各種型別的資料。無論是何種型別的資料,都會以二進位制序列的形式在網路上傳送。傳送方需要把這個Java物件轉換為位元組序列,才能在網路上傳送;接收方則需要把位元組序列再恢復為Java物件。

49.不通過建構函式也能建立物件嗎?

答:Java建立物件的幾種方式(重要):
1、 用new語句建立物件,這是最常見的建立物件的方法。
2、 運用反射手段,呼叫java.lang.Class或者java.lang.reflect.Constructor類的newInstance()例項方法。
3、 呼叫物件的clone()方法。
4、運用反序列化手段,呼叫java.io.ObjectInputStream物件的 readObject()方法。
(1)和(2)都會明確的顯式的呼叫建構函式 ;(3)是在記憶體上對已有物件的影印,所以不會呼叫建構函式 ;(4)是從檔案中還原類的物件,也不會呼叫建構函式。

50.匿名內部類可不可以繼承或實現介面。為什麼?

答:匿名內部類是沒有名字的內部類,不能繼承其它類,但一個內部類可以作為一個介面,由另一個內部類實現.
1、由於匿名內部類沒有名字,所以它沒有建構函式。因為沒有建構函式,所以它必須完全借用父類的建構函式來例項化,換言之:匿名內部類完全把建立物件的任務交給了父類去完成。
2、在匿名內部類裡建立新的方法沒有太大意義,但它可以通過覆蓋父類的方法達到神奇效果,如上例所示。這是多型性的體現。
3、因為匿名內部類沒有名字,所以無法進行向下的強制型別轉換,持有對一個匿名內部類物件引用的變數型別一定是它的直接或間接父類型別。

51.在Java中,為什麼基本型別不能做為HashMap的鍵值,而只能是引用型別?把引用型別做為HashMap的健值,需要注意哪些地方?

(1) 在Java中是使用泛型來約束HashMap中的key和value的型別的,即HashMap< K, V>;而泛型在Java的規定中必須是物件Object型別的,也就是說HashMap< K, V>可以理解為HashMap< Object, Object>,很顯然基本資料型別不是Object型別的,因此不能作為鍵值,只能是引用型別。雖然我們在HashMap中可以這樣新增資料:“map.put(1, “Java”);”,但實際上是將其中的key值1進行了自動裝箱操作,變為了Integer型別。
(2) 引用資料型別分為兩類:系統提供的引用資料型別(如包裝類、String 等)以及自定義引用資料型別。系統提供的引用資料型別中已經重寫了 HashCode()和 equals()兩個方法,所以能夠保證 Map 中 key 值的唯一性; 但是自定義的引用資料型別需要自己重寫 HashCode()和 equals()這兩個方 法 ,以保證 Map 中 key 值的唯一性。

52.簡述Java中如何實現多型

實現多型有三個前提條件:
1、 繼承的存在;(繼承是多型的基礎,沒有繼承就沒有多型)。
2、子類重寫父類的方法。(多型下會呼叫子類重寫後的方法)。
3、父類引用變數指向子類物件。(涉及子類到父類的型別轉換)。
最後**使用父類的引用變數呼叫子類重寫的方法即可實現多型**。

53.以下對繼承的描述錨誤的是 ()

選項內容
AJava中的繼承允許一個子類繼承多個父類
B父類更具有通用性,子類更具體
CJava中的繼承存在著傳遞性
D當例項化子類時會遞迴呼叫父類中的構造方法

答案:A
分析:Java是單繼承的,一個類只能繼承一個父類。

54.Java 中 Math.random()/Math.random()值為?

如果除數與被除數均為0.0的話,則執行結果為NaN(Not a Number的簡寫),計算錯誤。

55.介面和抽象類的區別

抽象類和介面均包含抽象方法,類必須實現所有的抽象方法,否則是抽象類

抽象類和介面都不能例項化,他們位於繼承樹的頂端,用來被其他類繼承和實現

兩者的區別主要體現在兩方面:語法方面和設計理念方面

語法方面的區別是比較低層次的,非本質的,主要表現在:
介面中只能定義全域性靜態常量,不能定義變數。抽象類中可以定義常量和變數。
介面中所有的方法都是全域性抽象方法。抽象類中可以有0個、1個或多個,甚至全部都是抽象方法。
抽象類中可以有構造方法,但不能用來例項化,而在子類例項化是執行,完成屬於抽象類的初始化操作。介面中不能定義構造方法。
一個類只能有一個直接父類(可以是抽象類),但可以充實實現多個介面。一個類使用extends來繼承抽象類,使用implements來實現介面。
一個類只能有一個直接父類(可以是抽象類),但可以充實實現多個介面。一個類使用extends來繼承抽象類,使用implements來實現介面。
抽象類體現了一種繼承關係,目的是複用程式碼,抽象類中定義了各個子類的相同程式碼,可以認為父類是一個實現了部分功能的“中間產品”,而子類是“最終產品”。父類和子類之間必須存在“is-a”的關係,即父類和子類在概念本質上應該是相同的。
介面並不要求實現類和介面在概念本質上一致的,僅僅是實現了介面定義的約定或者能力而已。介面定義了“做什麼”,而實現類負責完成“怎麼做”,體現了功能(規範)和實現分離的原則。介面和實現之間可以認為是一種“has-a的關係”

56.同步程式碼塊和同步方法有什麼區別

相同點:
同步方法就是在方法前加關鍵字synchronized,然後被同步的方法一次只能有一個執行緒進入,其他執行緒等待。而同步程式碼塊則是在方法內部使用大括號使得一個程式碼塊得到同步。同步程式碼塊會有一個同步的“目標”,使得同步塊更加靈活一些(同步程式碼塊可以通過“目標”決定需要鎖定的物件)。
一般情況下,如果此“目標”為this,同步方法和程式碼塊沒有太大的區別。
區別:
同步方法直接在方法上加synchronized實現加鎖,同步程式碼塊則在方法內部加鎖。很明顯,同步方法鎖的範圍比較大,而同步程式碼塊範圍要小點。一般同步的範圍越大,效能就越差。所以一般需要加鎖進行同步的時候,範圍越小越好,這樣效能更好。

57.靜態內部類和內部類有什麼區別

靜態內部類(在類裡的static類)不需要有指向外部類的引用。但非靜態內部類需要持有對外部類的引用。
靜態內部類可以有靜態成員(方法,屬性),而非靜態內部類則不能有靜態成員(方法,屬性)。
非靜態內部類能夠訪問外部類的靜態和非靜態成員。靜態內部類不能訪問外部類的非靜態成員,只能訪問外部類的靜態成員。
例項化方式不同:

  1. 靜態內部類:不依賴於外部類的例項,直接例項化內部類物件
  2. 非靜態內部類:通過外部類的物件例項生成內部類物件

相關文章