Java基礎 200319

、ZJL發表於2020-12-27

1. 為什麼要使用克隆?如何實現物件克隆?

Java 中的物件拷貝 (Object Copy) 指的是將一個物件的所有屬性(成員變數)拷貝到另一個有著相同類型別的物件中去。 在程式中拷貝物件是很常見的,主要是為了在新的上下文環境中複用現有物件的部分或全部資料。

Java 中的物件拷貝主要分為:淺拷貝 (Shallow Copy)、深拷貝 (Deep Copy)。

2. 深拷貝和淺拷貝區別是什麼?

淺拷貝只能應用於成員變數全是基本型別的物件,而深拷貝可以應用成員變數是物件的物件。

一般步驟是(淺複製):

被複制的類需要實現 Clonenable 介面(不實現的話在呼叫 clone 方法會丟擲 CloneNotSupportedException 異常) 該介面為標記介面 (不含任何方法)

覆蓋 clone () 方法,。方法中呼叫 super.clone () 方法得到需要的複製物件,注意該方法需要處理異常。

深拷貝的方式有兩種:

第一種:與通過重寫 clone 方法實現淺拷貝的基本思路一樣,只需要為物件圖的每一層的每一個物件都實現 Cloneable 介面並重寫 clone 方法,最後在最頂層的類的重寫的 clone 方法中呼叫所有的 clone 方法即可實現深拷貝。簡單的說就是:每一層的每個物件都進行淺拷貝 = 深拷貝。

第二種:結合序列化來解決這個問題,先把物件序列化,然後再反序列化成物件,該物件保證每個引用都是嶄新的。這個就形成了多個引用,原引用和反序列化之後的引用不在相同,具體實現:

3. 值傳遞和引用傳遞的區別是什麼?

值傳遞

在方法的呼叫過程中,實參把它的實際值傳遞給形參,此傳遞過程就是將實參的值複製一份傳遞到函式中,這樣如果在函式中對該值(形參的值)進行了操作將不會影響實參的值。因為是直接複製,所以這種方式在傳遞大量資料時,執行效率會特別低下。
引用傳遞

引用傳遞彌補了值傳遞的不足,如果傳遞的資料量很大,直接復過去的話,會佔用大量的記憶體空間,而引用傳遞就是將物件的地址值傳遞過去,函式接收的是原始值的首地址值。在方法的執行過程中,形參和實參的內容相同,指向同一塊記憶體地址,也就是說操作的其實都是源資料,所以方法的執行將會影響到實際物件。
4. 什麼是 java 序列化?什麼情況下需要序列化?如何避免序列化物件中的屬性序列化?

在 Java 中,我們可以通過多種方式來建立物件,並且只要物件沒有被回收我們都可以複用此物件。但是,建立出來的這些物件都存在於 JVM 中的堆(stack)記憶體中,只有 JVM 處於執行狀態的時候,這些物件才可能存在。一旦 JVM 停止,這些物件也就隨之消失;但是在真實的應用場景中,我們需要將這些物件持久化下來,並且在需要的時候將物件重新讀取出來,Java 的序列化可以幫助我們實現該功能。

物件序列化機制(object serialization)是 java 語言內建的一種物件持久化方式,通過物件序列化,可以將物件的狀態資訊儲存為位元組陣列,並且可以在有需要的時候將這個位元組陣列通過反序列化的方式轉換成物件,物件的序列化可以很容易的在 JVM 中的活動物件和位元組陣列(流)之間進行轉換。

Java 類通過實現 java.io.Serializable 介面來啟用序列化功能,未實現此介面的類將無法將其任何狀態或者資訊進行序列化或者反序列化。可序列化類的所有子型別都是可以序列化的。序列化介面沒有方法或者欄位,僅用於標識可序列化的語義。在 JAVA 中,物件的序列化和反序列化被廣泛的應用到 RMI(遠端方法呼叫)及網路傳輸中。

靜態資料不能被序列化,因為靜態資料不在堆記憶體中,而是在靜態方法區中

對於不需要序列化的屬性, java 的 transient 關鍵字為我們提供了便利,你只需要實現 Serilizable 介面,將不需要序列化的屬性前新增關鍵字 transient,序列化物件的時候,這個屬性就不會序列化到指定的目的地中。