日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

java关于异常的面试程序题_Java挑战:最难的十个面试题(附答案)「下」

發(fā)布時間:2023/12/4 java 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java关于异常的面试程序题_Java挑战:最难的十个面试题(附答案)「下」 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原標(biāo)題:Java挑戰(zhàn):最難的十個面試題(附答案)「下」

版權(quán)聲明:本文為CSDN博主「華為云」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.net/devcloud/article/details/100707463

————————————————

這是收集的10個最棘手的Java面試問題列表。這些問題主要來自 Java 核心部分 ,不涉及 Java EE 相關(guān)問題。你可能知道這些棘手的 Java 問題的答案,或者覺得這些不足以挑戰(zhàn)你的 Java 知識,但這些問題都是容易在各種 Java 面試中被問到的,而且包括我的朋友和同事在內(nèi)的許多程序員都覺得很難回答。

關(guān)于Java序列化的幾個面試問題

大多數(shù)商業(yè)項目使用數(shù)據(jù)庫或內(nèi)存映射文件或只是普通文件, 來滿足持久性要求, 只有很少的項目依賴于 Java 中的序列化過程。無論如何,這篇文章不是 Java 序列化教程或如何序列化在 Java 的對象, 但有關(guān)序列化機(jī)制和序列化 API 的面試問題, 這是值得去任何 Java 面試前先看看以免讓一些未知的內(nèi)容驚到自己。

對于那些不熟悉 Java 序列化的人, Java 序列化是用來通過將對象的狀態(tài)存儲到帶有.ser擴(kuò)展名的文件來序列化 Java 中的對象的過程, 并且可以通過這個文件恢復(fù)重建 Java對象狀態(tài), 這個逆過程稱為 deserialization。

什么是 Java 序列化?

序列化是把對象改成可以存到磁盤或通過網(wǎng)絡(luò)發(fā)送到其他運行中的 Java 虛擬機(jī)的二進(jìn)制格式的過程, 并可以通過反序列化恢復(fù)對象狀態(tài). Java 序列化API給開發(fā)人員提供了一個標(biāo)準(zhǔn)機(jī)制, 通過 java.io.Serializable 和 java.io.Externalizable 接口, ObjectInputStream 及ObjectOutputStream 處理對象序列化. Java 程序員可自由選擇基于類結(jié)構(gòu)的標(biāo)準(zhǔn)序列化或是他們自定義的二進(jìn)制格式, 通常認(rèn)為后者才是最佳實踐, 因為序列化的二進(jìn)制文件格式成為類輸出 API的一部分, 可能破壞 Java 中私有和包可見的屬性的封裝。

如何序列化?

讓 Java 中的類可以序列化很簡單. 你的 Java 類只需要實現(xiàn) java.io.Serializable 接口, JVM 就會把 Object 對象按默認(rèn)格式序列化. 讓一個類是可序列化的需要有意為之. 類可序列會可能為是一個長期代價, 可能會因此而限制你修改或改變其實現(xiàn). 當(dāng)你通過實現(xiàn)添加接口來更改類的結(jié)構(gòu)時, 添加或刪除任何字段可能會破壞默認(rèn)序列化, 這可以通過自定義二進(jìn)制格式使不兼容的可能性最小化, 但仍需要大量的努力來確保向后兼容性。序列化如何限制你更改類的能力的一個示例是 SerialVersionUID。

如果不顯式聲明 SerialVersionUID, 則 JVM 會根據(jù)類結(jié)構(gòu)生成其結(jié)構(gòu), 該結(jié)構(gòu)依賴于類實現(xiàn)接口和可能更改的其他幾個因素。假設(shè)你新版本的類文件實現(xiàn)的另一個接口, JVM 將生成一個不同的 SerialVersionUID 的, 當(dāng)你嘗試加載舊版本的程序序列化的舊對象時, 你將獲得無效類異常 InvalidClassException。

1) Java 中的可序列化接口和可外部接口之間的區(qū)別是什么?

這是 Java 序列化訪談中最常問的問題。下面是我的版本 Externalizable 給我們提供 writeExternal() 和 readExternal() 方法, 這讓我們靈活地控制 Java 序列化機(jī)制, 而不是依賴于 Java 的默認(rèn)序列化。正確實現(xiàn) Externalizable 接口可以顯著提高應(yīng)用程序的性能。

2) 可序列化的方法有多少?如果沒有方法,那么可序列化接口的用途是什么?

可序列化 Serializalbe 接口存在于java.io包中,構(gòu)成了 Java 序列化機(jī)制的核心。它沒有任何方法, 在 Java 中也稱為標(biāo)記接口。當(dāng)類實現(xiàn) java.io.Serializable 接口時, 它將在 Java 中變得可序列化, 并指示編譯器使用 Java 序列化機(jī)制序列化此對象。

3) 什么是 serialVersionUID ?如果你不定義這個, 會發(fā)生什么?

我最喜歡的關(guān)于Java序列化的問題面試問題之一。serialVersionUID 是一個 private static final long 型 ID, 當(dāng)它被印在對象上時, 它通常是對象的哈希碼,你可以使用 serialver 這個 JDK 工具來查看序列化對象的 serialVersionUID。SerialVerionUID 用于對象的版本控制。也可以在類文件中指定 serialVersionUID。不指定 serialVersionUID的后果是,當(dāng)你添加或修改類中的任何字段時, 則已序列化類將無法恢復(fù), 因為為新類和舊序列化對象生成的 serialVersionUID 將有所不同。Java 序列化過程依賴于正確的序列化對象恢復(fù)狀態(tài)的, ,并在序列化對象序列版本不匹配的情況下引發(fā) java.io.InvalidClassException 無效類異常,了解有關(guān) serialVersionUID 詳細(xì)信息,請參閱這篇文章, 需要 FQ。

4) 序列化時,你希望某些成員不要序列化?你如何實現(xiàn)它?

另一個經(jīng)常被問到的序列化面試問題。這也是一些時候也問, 如什么是瞬態(tài) trasient 變量, 瞬態(tài)和靜態(tài)變量會不會得到序列化等,所以,如果你不希望任何字段是對象的狀態(tài)的一部分, 然后聲明它靜態(tài)或瞬態(tài)根據(jù)你的需要, 這樣就不會是在 Java 序列化過程中被包含在內(nèi)。問題

5) 如果類中的一個成員未實現(xiàn)可序列化接口, 會發(fā)生什么情況?

關(guān)于Java序列化過程的一個簡單問題。如果嘗試序列化實現(xiàn)可序列化的類的對象,但該對象包含對不可序列化類的引用,則在運行時將引發(fā)不可序列化異常 NotSerializableException, 這就是為什么我始終將一個可序列化警報(在我的代碼注釋部分中), 代碼注釋最佳實踐之一, 指示開發(fā)人員記住這一事實, 在可序列化類中添加新字段時要注意。

6) 如果類是可序列化的, 但其超類不是, 則反序列化后從超級類繼承的實例變量的狀態(tài)如何?

Java 序列化過程僅在對象層次都是可序列化結(jié)構(gòu)中繼續(xù), 即實現(xiàn) Java 中的可序列化接口, 并且從超級類繼承的實例變量的值將通過調(diào)用構(gòu)造函數(shù)初始化, 在反序列化過程中不可序列化的超級類。一旦構(gòu)造函數(shù)鏈接將啟動, 就不可能停止, 因此, 即使層次結(jié)構(gòu)中較高的類實現(xiàn)可序列化接口, 也將執(zhí)行構(gòu)造函數(shù)。正如你從陳述中看到的, 這個序列化面試問題看起來非常棘手和有難度, 但如果你熟悉關(guān)鍵概念, 則并不難。

7) 是否可以自定義序列化過程, 或者是否可以覆蓋 Java 中的默認(rèn)序列化過程?

答案是肯定的, 你可以。我們都知道,對于序列化一個對象需調(diào)用 ObjectOutputStream.writeObject(saveThisObject), 并用 ObjectInputStream.readObject() 讀取對象, 但 Java 虛擬機(jī)為你提供的還有一件事, 是定義這兩個方法。如果在類中定義這兩種方法, 則 JVM 將調(diào)用這兩種方法, 而不是應(yīng)用默認(rèn)序列化機(jī)制。你可以在此處通過執(zhí)行任何類型的預(yù)處理或后處理任務(wù)來自定義對象序列化和反序列化的行為。

需要注意的重要一點是要聲明這些方法為私有方法, 以避免被繼承、重寫或重載。由于只有 Java 虛擬機(jī)可以調(diào)用類的私有方法, 你的類的完整性會得到保留, 并且 Java 序列化將正常工作。在我看來, 這是在任何 Java 序列化面試中可以問的最好問題之一, 一個很好的后續(xù)問題是, 為什么要為你的對象提供自定義序列化表單?

8) 假設(shè)新類的超級類實現(xiàn)可序列化接口, 如何避免新類被序列化?

在 Java 序列化中一個棘手的面試問題。如果類的 Super 類已經(jīng)在 Java 中實現(xiàn)了可序列化接口, 那么它在 Java 中已經(jīng)可以序列化, 因為你不能取消接口, 它不可能真正使它無法序列化類, 但是有一種方法可以避免新類序列化。為了避免 Java 序列化,你需要在類中實現(xiàn) writeObject() 和 readObject() 方法, 并且需要從該方法引發(fā)不序列化異常NotSerializableException。這是自定義 Java 序列化過程的另一個好處, 如上述序列化面試問題中所述, 并且通常隨著面試進(jìn)度, 它作為后續(xù)問題提出。

9) 在 Java 中的序列化和反序列化過程中使用哪些方法?

這是很常見的面試問題, 在序列化基本上面試官試圖知道: 你是否熟悉 readObject() 的用法、writeObject()、readExternal() 和 writeExternal()。Java 序列化由java.io.ObjectOutputStream類完成。該類是一個篩選器流, 它封裝在較低級別的字節(jié)流中, 以處理序列化機(jī)制。要通過序列化機(jī)制存儲任何對象, 我們調(diào)用 ObjectOutputStream.writeObject(savethisobject), 并反序列化該對象, 我們稱之為 ObjectInputStream.readObject()方法。調(diào)用以 writeObject() 方法在 java 中觸發(fā)序列化過程。關(guān)于 readObject() 方法, 需要注意的一點很重要一點是, 它用于從持久性讀取字節(jié), 并從這些字節(jié)創(chuàng)建對象, 并返回一個對象, 該對象需要類型強制轉(zhuǎn)換為正確的類型。

10) 假設(shè)你有一個類,它序列化并存儲在持久性中, 然后修改了該類以添加新字段。如果對已序列化的對象進(jìn)行反序列化, 會發(fā)生什么情況?

這取決于類是否具有其自己的 serialVersionUID。正如我們從上面的問題知道, 如果我們不提供 serialVersionUID, 則 Java 編譯器將生成它, 通常它等于對象的哈希代碼。通過添加任何新字段, 有可能為該類新版本生成的新 serialVersionUID 與已序列化的對象不同, 在這種情況下, Java 序列化 API 將引發(fā) java.io.InvalidClassException, 因此建議在代碼中擁有自己的 serialVersionUID, 并確保在單個類中始終保持不變。

11) Java序列化機(jī)制中的兼容更改和不兼容更改是什么?

真正的挑戰(zhàn)在于通過添加任何字段、方法或刪除任何字段或方法來更改類結(jié)構(gòu), 方法是使用已序列化的對象。根據(jù) Java 序列化規(guī)范, 添加任何字段或方法都面臨兼容的更改和更改類層次結(jié)構(gòu)或取消實現(xiàn)的可序列化接口, 有些接口在非兼容更改下。對于兼容和非兼容更改的完整列表, 我建議閱讀 Java 序列化規(guī)范。

12) 我們可以通過網(wǎng)絡(luò)傳輸一個序列化的對象嗎?

是的 ,你可以通過網(wǎng)絡(luò)傳輸序列化對象, 因為 Java 序列化對象仍以字節(jié)的形式保留, 字節(jié)可以通過網(wǎng)絡(luò)發(fā)送。你還可以將序列化對象存儲在磁盤或數(shù)據(jù)庫中作為 Blob。

13) 在 Java 序列化期間,哪些變量未序列化?

這個問題問得不同, 但目的還是一樣的, Java開發(fā)人員是否知道靜態(tài)和瞬態(tài)變量的細(xì)節(jié)。由于靜態(tài)變量屬于類, 而不是對象, 因此它們不是對象狀態(tài)的一部分, 因此在 Java 序列化過程中不會保存它們。由于 Java 序列化僅保留對象的狀態(tài),而不是對象本身。瞬態(tài)變量也不包含在 Java 序列化過程中, 并且不是對象的序列化狀態(tài)的一部分。在提出這個問題之后,面試官會詢問后續(xù)內(nèi)容, 如果你不存儲這些變量的值, 那么一旦對這些對象進(jìn)行反序列化并重新創(chuàng)建這些變量, 這些變量的價值是多少?這是你們要考慮的。

為什么Java中 wait 方法需要在 synchronized 的方法中調(diào)用?

另一個棘手的核心 Java 問題,wait 和 notify。它們是在有 synchronized 標(biāo)記的方法或 synchronized 塊中調(diào)用的,因為 wait 和 modify 需要監(jiān)視對其上調(diào)用 wait 或 notify-get 的 Object。

大多數(shù)Java開發(fā)人員都知道對象類的 wait(),notify() 和 notifyAll()方法必須在Java中的 synchronized 方法或 synchronized 塊中調(diào)用, 但是我們想過多少次, 為什么在 Java 中 wait, notify 和 notifyAll 來自 synchronized 塊或方法?

最近這個問題在Java面試中被問到我的一位朋友,他思索了一下,并回答說: 如果我們不從同步上下文中調(diào)用 wait() 或 notify() 方法,我們將在 Java 中收到 IllegalMonitorStateException。

他的回答從實際效果上年是正確的,但面試官對這樣的答案不會完全滿意,并希望向他解釋這個問題。面試結(jié)束后 他和我討論了同樣的問題,我認(rèn)為他應(yīng)該告訴面試官關(guān)于 Java 中 wait()和 notify()之間的競態(tài)條件,如果我們不在同步方法或塊中調(diào)用它們就可能存在。

讓我們看看競態(tài)條件如何在Java程序中發(fā)生。它也是流行的線程面試問題之一,并經(jīng)常在電話和面對面的Java開發(fā)人員面試中出現(xiàn)。因此,如果你正在準(zhǔn)備Java面試,那么你應(yīng)該準(zhǔn)備這樣的問題,并且可以真正幫助你的一本書是《Java程序員面試公式書》的。這是一本罕見的書,涵蓋了Java訪談的幾乎所有重要主題,例如核心Java,多線程,IO 和 NIO 以及 Spring 和 Hibernate 等框架。你可以在這里查看。

為什么要等待來自 Java中的 synchronized 方法的 wait方法為什么必須從 Java 中的 synchronized 塊或方法調(diào)用 ?我們主要使用 wait(),notify() 或 notifyAll() 方法用于 Java 中的線程間通信。一個線程在檢查條件后正在等待,例如,在經(jīng)典的生產(chǎn)者 - 消費者問題中,如果緩沖區(qū)已滿,則生產(chǎn)者線程等待,并且消費者線程通過使用元素在緩沖區(qū)中創(chuàng)建空間后通知生產(chǎn)者線程。調(diào)用notify()或notifyAll()方法向單個或多個線程發(fā)出一個條件已更改的通知,并且一旦通知線程離開 synchronized 塊,正在等待的所有線程開始獲取正在等待的對象鎖定,幸運的線程在重新獲取鎖之后從 wait() 方法返回并繼續(xù)進(jìn)行。

讓我們將整個操作分成幾步,以查看Java中wait()和notify()方法之間的競爭條件的可能性,我們將使用Produce Consumer 線程示例更好地理解方案:

Producer 線程測試條件(緩沖區(qū)是是否完整)并確認(rèn)必須等待(找到緩沖區(qū)已滿)。Consumer 線程在使用緩沖區(qū)中的元素后設(shè)置條件。Consumer 線程調(diào)用 notify() 方法; 這是不會被聽到的,因為 Producer 線程還沒有等待。Producer 線程調(diào)用 wait() 方法并進(jìn)入等待狀態(tài)。

因此,由于競態(tài)條件,我們可能會丟失通知,如果我們使用緩沖區(qū)或只使用一個元素,生產(chǎn)線程將永遠(yuǎn)等待,你的程序?qū)炱稹!霸趈ava同步中等待 notify 和 notifyall 現(xiàn)在讓我們考慮如何解決這個潛在的競態(tài)條件?

這個競態(tài)條件通過使用 Java 提供的 synchronized 關(guān)鍵字和鎖定來解決。為了調(diào)用 wait(),notify() 或 notifyAll(), 在Java中,我們必須獲得對我們調(diào)用方法的對象的鎖定。由于 Java 中的 wait() 方法在等待之前釋放鎖定并在從 wait() 返回之前重新獲取鎖定方法,我們必須使用這個鎖來確保檢查條件(緩沖區(qū)是否已滿)和設(shè)置條件(從緩沖區(qū)獲取元素)是原子的,這可以通過在 Java 中使用 synchronized 方法或塊來實現(xiàn)。

我不確定這是否是面試官實際期待的,但這個我認(rèn)為至少有意義,請糾正我如果我錯了,請告訴我們是否還有其他令人信服的理由調(diào)用 wait(),notify() 或 Java 中的 notifyAll() 方法。

總結(jié)一下,我們用 Java 中的 synchronized 方法或 synchronized 塊調(diào)用 Java 中的 wait(),notify() 或 notifyAll() 方法來避免:

1) Java 會拋出 IllegalMonitorStateException,如果我們不調(diào)用來自同步上下文的wait(),notify()或者notifyAll()方法。

2) Javac 中 wait 和 notify 方法之間的任何潛在競爭條件。

你能用Java覆蓋靜態(tài)方法嗎?如果我在子類中創(chuàng)建相同的方法是編譯時錯誤?

不,你不能在Java中覆蓋靜態(tài)方法,但在子類中聲明一個完全相同的方法不是編譯時錯誤,這稱為隱藏在Java中的方法。

你不能覆蓋Java中的靜態(tài)方法,因為方法覆蓋基于運行時的動態(tài)綁定,靜態(tài)方法在編譯時使用靜態(tài)綁定進(jìn)行綁定。雖然可以在子類中聲明一個具有相同名稱和方法簽名的方法,看起來可以在Java中覆蓋靜態(tài)方法,但實際上這是方法隱藏。Java不會在運行時解析方法調(diào)用,并且根據(jù)用于調(diào)用靜態(tài)方法的 Object 類型,將調(diào)用相應(yīng)的方法。這意味著如果你使用父類的類型來調(diào)用靜態(tài)方法,那么原始靜態(tài)將從父類中調(diào)用,另一方面如果你使用子類的類型來調(diào)用靜態(tài)方法,則會調(diào)用來自子類的方法。簡而言之,你無法在Java中覆蓋靜態(tài)方法。如果你使用像Eclipse或Netbeans這樣的Java IDE,它們將顯示警告靜態(tài)方法應(yīng)該使用類名而不是使用對象來調(diào)用,因為靜態(tài)方法不能在Java中重寫。

輸出:

此輸出確認(rèn)你無法覆蓋Java中的靜態(tài)方法,并且靜態(tài)方法基于類型信息而不是基于Object進(jìn)行綁定。如果要覆蓋靜態(tài)mehtod,則會調(diào)用子類或 ColorScreen 中的方法。這一切都在討論中我們可以覆蓋Java中的靜態(tài)方法。我們已經(jīng)確認(rèn)沒有,我們不能覆蓋靜態(tài)方法,我們只能在Java中隱藏靜態(tài)方法。創(chuàng)建具有相同名稱和mehtod簽名的靜態(tài)方法稱為Java隱藏方法。IDE將顯示警告:"靜態(tài)方法應(yīng)該使用類名而不是使用對象來調(diào)用", 因為靜態(tài)方法不能在Java中重寫。

這些是我的核心Java面試問題和答案的清單。對于有經(jīng)驗的程序員來說,一些Java問題看起來并不那么難,但對于Java中的中級和初學(xué)者來說,它們真的很難回答。返回搜狐,查看更多

責(zé)任編輯:

總結(jié)

以上是生活随笔為你收集整理的java关于异常的面试程序题_Java挑战:最难的十个面试题(附答案)「下」的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。