熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Javascript >> 正文

必須執行清除

2022-06-13   來源: Javascript 

  
  為清除一個對象那個對象的用戶必須在希望進行清除的地點調用一個清除方法這聽起來似乎很容易做到但卻與C++破壞器的概念稍有抵觸在C++中所有對象都會破壞(清除)或者換句話說所有對象都應該破壞若將C++對象創建成一個本地對象比如在堆棧中創建(在Java中是不可能的)那麼清除或破壞工作就會在結束花括號所代表的創建這個對象的作用域的末尾進行若對象是用new創建的(類似於Java)那麼當程序員調用C++的delete命令時(Java沒有這個命令)就會調用相應的破壞器若程序員忘記了那麼永遠不會調用破壞器我們最終得到的將是一個內存漏洞另外還包括對象的其他部分永遠不會得到清除
  相反Java不允許我們創建本地(局部)對象——無論如何都要使用new但在Java中沒有delete命令來釋放對象因為垃圾收集器會幫助我們自動釋放存儲空間所以如果站在比較簡化的立場我們可以說正是由於存在垃圾收集機制所以Java沒有破壞器然而隨著以後學習的深入就會知道垃圾收集器的存在並不能完全消除對破壞器的需要或者說不能消除對破壞器代表的那種機制的需要(而且絕對不能直接調用finalize()所以應盡量避免用它)若希望執行除釋放存儲空間之外的其他某種形式的清除工作仍然必須調用Java中的一個方法它等價於C++的破壞器只是沒後者方便
  finalize()最有用處的地方之一是觀察垃圾收集的過程下面這個例子向大家展示了垃圾收集所經歷的過程並對前面的陳述進行了總結
  
  //: Garbagejava
  // Demonstration of the garbage
  // collector and finalization
  
  class Chair {
   static boolean gcrun = false;
   static boolean f = false;
   static int created = ;
   static int finalized = ;
   int i;
   Chair() {
    i = ++created;
    if(created == )
     Systemoutprintln(Created );
   }
   protected void finalize() {
    if(!gcrun) {
     gcrun = true;
     Systemoutprintln(
      Beginning to finalize after +
      created + Chairs have been created);
    }
    if(i == ) {
     Systemoutprintln(
      Finalizing Chair # +
      Setting flag to stop Chair creation);
     f = true;
    }
    finalized++;
    if(finalized >= created)
     Systemoutprintln(
      All + finalized + finalized);
   }
  }
  
  public class Garbage {
   public static void main(String[] args) {
    if(argslength == ) {
     Systemerrprintln(Usage: \n +
      java Garbage before\n or:\n +
      java Garbage after);
     return;
    }
    while(!Chairf) {
     new Chair();
     new String(To take up space);
    }
    Systemoutprintln(
     After all Chairs have been created:\n +
     total created = + Chaircreated +
      total finalized = + Chairfinalized);
    if(args[]equals(before)) {
     Systemoutprintln(gc():);
     Systemgc();
     Systemoutprintln(runFinalization():);
     SystemrunFinalization();
    }
    Systemoutprintln(bye!);
    if(args[]equals(after))
     SystemrunFinalizersOnExit(true);
   }
  } ///:~
  
  上面這個程序創建了許多Chair對象而且在垃圾收集器開始運行後的某些時候程序會停止創建Chair由於垃圾收集器可能在任何時間運行所以我們不能准確知道它在何時啟動因此程序用一個名為gcrun的標記來指出垃圾收集器是否已經開始運行利用第二個標記fChair可告訴main()它應停止對象的生成這兩個標記都是在finalize()內部設置的它調用於垃圾收集期間
  另兩個static變量——created以及finalized——分別用於跟蹤已創建的對象數量以及垃圾收集器已進行完收尾工作的對象數量最後每個Chair都有它自己的(非static)int i所以能跟蹤了解它具體的編號是多少編號為的Chair進行完收尾工作後標記會設為true最終結束Chair對象的創建過程
  所有這些都在main()的內部進行——在下面這個循環裡
  
  while(!Chairf) {
  new Chair();
  new String(To take up space);
  }
  
  大家可能會疑惑這個循環什麼時候會停下來因為內部沒有任何改變Chairf值的語句然而finalize()進程會改變這個值直至最終對編號的對象進行收尾處理
  每次循環過程中創建的String對象只是屬於額外的垃圾用於吸引垃圾收集器——一旦垃圾收集器對可用內存的容量感到緊張不安就會開始關注它
  運行這個程序的時候提供了一個命令行自變量before或者after其中before自變量會調用Systemgc()方法(強制執行垃圾收集器)同時還會調用SystemrunFinalization()方法以便進行收尾工作這些方法都可在Java 中使用但通過使用after自變量而調用的runFinalizersOnExit()方法卻只有Java 及後續版本提供了對它的支持(注釋③)注意可在程序執行的任何時候調用這個方法而且收尾程序的執行與垃圾收集器是否運行是無關的
  
  ③不幸的是Java 采用的垃圾收集器方案永遠不能正確地調用finalize()因此finalize()方法(特別是那些用於關閉文件的)事實上經常都不會得到調用現在有些文章聲稱所有收尾模塊都會在程序退出的時候得到調用——即使到程序中止的時候垃圾收集器仍未針對那些對象采取行動這並不是真實的情況所以我們根本不能指望finalize()能為所有對象而調用特別地finalize()在Java 裡幾乎毫無用處
  
  前面的程序向我們揭示出在Java 收尾模塊肯定會運行這一許諾已成為現實——但前提是我們明確地強制它采取這一操作若使用一個不是beforeafter的自變量(如none那麼兩個收尾工作都不會進行而且我們會得到象下面這樣的輸出
  Created
  
  
  Created
  Beginning to finalize after Chairs have been created
  Finalizing Chair # Setting flag to stop Chair creation
  After all Chairs have been created:
  total created = total finalized =
  bye!
  
  因此到程序結束的時候並非所有收尾模塊都會得到調用為強制進行收尾工作可先調用Systemgc()再調用SystemrunFinalization()這樣可清除到目前為止沒有使用的所有對象這樣做一個稍顯奇怪的地方是在調用runFinalization()之前調用gc()這看起來似乎與Sun公司的文檔說明有些抵觸它宣稱首先運行收尾模塊再釋放存儲空間然而若在這裡首先調用runFinalization()再調用gc()收尾模塊根本不會執行
  
  針對所有對象Java 有時之所以會默認為跳過收尾工作是由於它認為這樣做的開銷太大不管用哪種方法強制進行垃圾收集都可能注意到比沒有額外收尾工作時較長的時間延遲
From:http://tw.wingwit.com/Article/program/Java/Javascript/201311/25304.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.