JavaRush /Java Blog /Random-TW /物件生命週期

物件生命週期

在 Random-TW 群組發布
你好!我想如果我們告訴您電腦上的記憶體大小是有限的,您不會太驚訝:)即使是比 RAM 大很多倍的硬碟,也可以填滿您最喜歡的遊戲、電視節目、等等。為了防止這種情況發生,您需要監視記憶體的當前狀態並從電腦中刪除不必要的檔案。Java 程式設計與這一切有什麼關係?直接的!畢竟,當 Java 機器創建任何物件時,都會為其分配記憶體。在一個真正的大型程式中,會創建數以萬計的對象,每個對像都分配自己的一塊記憶體。物件生命週期 - 1但你認為所有這些物體存在多久了?它們在我們的程式運行的整個過程中都「存在」嗎?當然不是。儘管具有 Java 物件的所有優點,但它們並不是不朽的:) 物件有自己的生命週期。今天我們就寫程式碼休息一下,看看這個過程:)而且,它對於理解程式的運作和管理資源非常重要。那麼,物體的生命從哪裡開始呢?喜歡一個人-從他出生,也就是創作開始。
Cat cat = new Cat();//вот сейчас и начался vital цикл нашего an object Cat!
首先,Java 虛擬機器分配必要的記憶體量來建立物件。然後她創建了一個指向它的鏈接,在我們的例子中 -cat以便能夠跟踪它。之後,所有變數都被初始化,構造函數被調用,你瞧,我們的新物件已經有了自己的生命:) 物件的壽命是不同的,這裡沒有確切的數字。無論如何,它都會在程式中存在一段時間並執行其功能。準確地說,只要存在對某個物件的引用,該物件就是「活著的」。一旦不再有任何鏈接,該對象就會“死亡”。例如:
public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}
在這個方法中,main()蘭博基尼暗黑破壞神汽車物件已經在第二行不再存在。原來只有一個鏈接,現在這個鏈接已經被分配了null。由於沒有留下任何關於蘭博基尼暗黑破壞神的參考資料,它變成了「垃圾」。無需重置連結:
public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}
這裡我們創建了第二個對象,之後我們獲取引用lamborghini並將其分配給這個新對象。現在有Lamborghini Gallardo兩個對該物件的引用,但Lamborghini Diablo沒有一個對該物件的引用。因此該物件Diablo就變成了垃圾。而這時候,Java內建的機制──垃圾收集器,或是說──垃圾收集器,GC就開始運作了。
物件生命週期 - 2
垃圾收集器是 Java 的一種內部機制,負責釋放內存,即從中刪除不需要的物件。我們選擇一張帶有機器人吸塵器的圖片來描繪它並不是沒有原因的。畢竟,垃圾收集器的工作方式大致相同:在後台,它「遍歷」您的程序,收集垃圾,同時您實際上不與它互動。它的工作是刪除程式中不再使用的物件。因此,它為其他物件釋放了電腦中的記憶體。您還記得在講座開始時我們說過,在日常生活中您必須監控計算機的狀態並刪除舊文件嗎?因此,對於 Java 對象,垃圾收集器會為您執行此操作。垃圾收集器在程式運行期間會啟動多次:不需要專門呼叫它並給出命令,儘管這在技術上是可行的。稍後我們將詳細討論它並更詳細地分析它的工作過程。當垃圾收集器到達該物件時,就在其銷毀之前,會在該物件上呼叫一個特殊方法 - finalize()。它可用於釋放物件正在使用的一些額外資源。該方法finalize()屬於該類別Object。也就是說,除了您之前已經見過的equals()hashCode()和 之外,任何物件都具有它。toString()它與其他方法的不同之處在於,它……怎麼說呢……非常任性。也就是說,在銷毀物件之前並不總是呼叫它。程式設計是一件精確的事。程式設計師告訴電腦做某件事,計算機就會做。您可能已經習慣了這種行為,一開始您可能很難接受這個想法:“在物件被銷毀之前,請呼叫finalize()類別方法Object。” 或者它沒有被呼叫。如果我們運氣好的話!” 然而,這是事實。Java 機器本身決定是否finalize()在每種特定情況下呼叫該方法。例如,為了進行實驗,我們嘗試執行以下程式碼:
public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {

       for (int i = 0 ; i < 1000000; i++) {

           Cat cat = new Cat();
           cat = null;//вот здесь первый an object становится доступен сборщику мусора
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("Объект Cat уничтожен!");
   }
}
我們建立一個對象Cat,並在下一行程式碼中重置對它的唯一參考。如此——一百萬次。我們已經明確地重寫了該方法finalize(),並且它應該在每次銷毀物件之前將字串列印到控制台一百萬次Cat。但不是!準確的說,它在我的電腦上只運行了37,346次!也就是說,我安裝的 Java 機器在 27 種情況中只有 1 種決定調用某個方法finalize()- 在其他情況下,垃圾收集會在沒有這種情況下繼續進行。嘗試自己運行此程式碼:結果很可能會有所不同。正如你所看到的,finalize()很難稱其為可靠的合作夥伴:)因此,對未來的一點建議:finalize()在釋放一些關鍵資源的情況下,你不應該依賴該方法。也許 JVM 會呼叫它,也許不會。誰知道?如果您的物件在其生命週期內佔用了一些對效能非常重要的資源,例如,它保持與資料庫的開放連接,那麼最好在您的類別中建立一個特殊的方法來釋放它們,並在物件被釋放時顯式調用它。不再需要。這樣您就可以確定程式的效能不會受到影響。一開始我們就說過記憶體管理和垃圾清除非常重要,確實如此。對資源的不當處理以及對組裝不必要物件的過程缺乏了解可能會導致記憶體洩漏。這是最著名的程式錯誤之一。程式設計師錯誤編寫的程式碼可能會導致每次為新創建的物件分配新的內存,而垃圾收集器無法刪除舊的、不必要的物件。既然我們用機器人吸塵器做了類比,想像一下,如果在啟動機器人之前,你把襪子散落在房子周圍,打碎了一個玻璃花瓶,並將拆解後的樂高積木留在地板上,會發生什麼。當然,機器人會嘗試做某件事,但在某個時刻它會卡住。
物件生命週期 - 3
為了使其正常工作,您需要保持地板狀況良好,並清除吸塵器無法處理的所有物品。垃圾收集器的工作原理相同。如果程式中存在大量無法收集的物件(例如襪子或機器人吸塵器的樂高積木),那麼記憶體將在某個時刻耗盡。不僅你寫的程式會凍結,此時電腦上執行的所有其他程式也會凍結。他們也沒有足夠的內存。這就是 Java 中物件生命週期和垃圾收集器的樣子。無需記住這一點:只需了解操作原理即可。在下一講中,我們將更詳細地討論這些過程,但現在您可以返回解決 JavaRush 問題:) 祝您好運!
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION