I want to fly higher
          programming Explorer
          posts - 114,comments - 263,trackbacks - 0

          初始化和清理
              1.this關鍵字
               如果有同一個類型的兩個對象a和b,如何才能讓這兩個對象同時調用peel方法呢:
              如:
               Banana a = new Banana();
               Banana b = new Banana;
               a.peel(1);
               b.peel(2);
               如果只有一個peel方法,它如何知道是被a還是b調用呢?
               為了能用簡便,面向對象的語法來編寫代碼,即"發送消息給對象";編譯器做了一些幕后工作,他暗自把“所操作對象的引用”作為第一個參數傳遞給了peel->所以上述兩個方法的調用變成了這樣:a.peel(a,1),b.peel(b,1);這是內部的表示形式;雖然我們不能這樣書寫代碼,并試圖通過編譯,不過這種寫法的確能幫你了解實際發生的事情。
           如果你希望在方法內部獲得對當前對象的引用,由于這個引用是編譯器“偷偷”傳入的,沒有什么標識符可用;但為此有一個專門的關鍵字:this;this關鍵字只能在方法內部使用,表示“對調用方法的那個對象”的引用;
           當前方法的this引用會自動引用于同一類的其他方法->
           只有當需要明確指出對當前對象引用的時候,才需要使用this關鍵字;如需要返回當前對象的引用的時候,就常常在return語句里這樣寫:
           return this;
           
               注:有人執意將this放在每一個方法調用和字段引用前,認為這樣“更清晰更明確”。但是千萬別這么做,我們使用高級語言的原因之一就是它幫我們做一些事情。要是把this放在一些沒有必要的地方,就會使讀你程序的人不知所措,因為別人寫的代碼不會到處用this。遵循一種一致而直觀的編程風格能節省時間和金錢.
               1.通過this返回對當前對象的引用,所以很容易在一條語句中對同一個對象執行多種操作;
               2.一些必要的地方才需要調用this
               3.構造器中調用構造器,this添加參數列表-產生對符合此列表的某個構造器的明確調用(除構造器之外,編譯器禁止在其他任何方法調用構造器)
               4.解決參數名稱和數據成員名稱一致,數據成員采用this.的形式引用
               5.static方法就是沒有this的方法,在static方法的內部不能調用非靜態方法(這不是完全不可能,如果你傳遞一個對象的引用到靜態方法里(靜態方法可以創建其自身的對象),然后通過這個引用(和this效果相同)就可以調用非靜態方法和訪問非靜態數據成員了。但通常要達到這樣的效果,你只需寫一個非靜態方法即可);反過來可以;可以在沒有創建對象的前提下;僅僅通過類本身調用static方法,這實際上正是static方法的主要用途;
               有些人認為static不是面向對象的,因為它的確具有全局函數的語義;使用static方法時,由于不存在this,所以不是通過“向對象發送消息”的方式來完成的;的確,要是在代碼中出現了大量的static方法,就該重新考慮一下自己的設計了;然而static的概念有其實用之處,許多時候都用到它;對于它是否真的面向對象,留給理論家去討論吧;
           
             2.終結清理和垃圾回收
               1.對象可能不被垃圾回收
               2.垃圾回收并不等于析構
               3.垃圾回收只與內存有關
                垃圾回收本身也有開銷
            finalize:
                 假定工作原理:一旦垃圾回收器準備好釋放對象占用的存儲空間,將首先調用finalize方法,并且在下一次垃圾回收動作發生時,才會真正的回收對象占用的內存;【不過要是“垃圾回收”沒有發生的話,則無法釋放;這個策略是恰當的,只要程序沒有瀕臨存儲空間用完的一刻;對象占用的空間總也得不到釋放;因為垃圾回收也是有開銷的】
                通過某種創建對象方式以外的方式為對象分配了存儲空間:是由于在分配內存的時候可能使用了C語言的做法,這種做法主要發生在使用“本地”方法的情況下;本地方法是一種在Java中調用非Java代碼的方式。本地方法目前只支持C/C++,但他們可以調用其他語言寫的代碼,所以實際上可以調用任何代碼;非Java代碼中,也許會調用類似C的的malloc函數系列來分配存儲空間,而且除非調用了free函數,否則存儲空間將得不到釋放,從而造成內存泄露;當然free是C/C++的函數,所以要在finalize中用本地方法調用它;
                【記?。簾o論是垃圾回收還是終結,都不保證一定會發生。如果Java虛擬(jvm)并未面臨內存耗盡的情況,它是不會浪費時間去執行垃圾回收以恢復內存的】
            
              3.Java堆模型
               1.一些java虛擬機的堆實現中,更像一個傳送帶,每分配一個新對象,就往前移動一格;對象存儲空間的分配速度非???,Java的“堆”指針只是簡單的移動到尚未分配的區域;(C++的堆像一個院子,每個對象都負責管理自己的地盤,一段時間后,對象可能被銷毀,但地盤必須加以重用);不過Java的堆并不完全像傳送帶那樣工作,否則會導致頻繁的內存頁面調度,會顯著影響性能;而垃圾回收介入之后,它工作時,一面回收空間,一面使隊中的對象緊湊排列,這樣“堆指針”就可以很容易移動到更靠近傳送帶的開始處;也就盡量避免了頁面錯誤->通過垃圾回收器對對象重新排列,實現了一種告訴的,有無限空間可供分配的堆模型.
           
              4.垃圾回收機制:
                   1.引用計數:垃圾回收器在含有全部對象的列表遍歷,發現某個對象的引用計數為0,就是釋放其占用的空間;不過對于對象之間的循環引用,則會出現“對象應該被回收,不過引用計數不為0”;對于垃圾回收器而言,定位這樣的交叉引用的對象組所需的工作量極大;
                   2.更快的模式:對任何“活”的對象,一定能最終追溯到其存活在堆?;蜢o態存儲區之中的引用;因此,如果從堆棧和靜態存儲區開始,遍歷所有的引用,就能找到所有活著的對象;
                   停止-復制
                    標記-清掃
                兩種方式程序將暫停
                自適應的,分代的,停止-復制,標記-清掃式垃圾回收器
               3.java虛擬機許多附加技術->JIT(just in time)編譯器技術->
                    新版JDK的Java HotSpot技術
              6.初始化
               1.方法局部變量,編譯時錯誤保證;【當然編譯器可以為局部變量賦一個默認值,不過未初始化的局部變量更有可能是程序員的疏忽,所以采用默認值反而會掩蓋這種失誤,因此強制程序員提供一個初始值,往往可以找到程序中的bug】
               2.類的內部,變量定義的先后順序決定了初始化的順序;會在任何方法(包括構造器)被調用之前得到初始化
               3.靜態數據初始化,無論創建多少個對象,靜態數據都只占用一份存儲區域->靜態初始化只有在必要時才進行->
               4.構造器可以看成是靜態方法;首次創建類對象/訪問類的靜態方法,靜態域->載入類.class->靜態初始化,只在class加載的時候初始化一次->new,在堆上為該對象分配足夠的存儲空間->這塊存儲空間請0,所有基本類型被置默認值,引用null->執行所有出現于字段定義處的初始化動作->執行構造器->
               5.static{},靜態子句;{},實例初始化子句;
               6.數組初始化int[]array= {};int[] array = new int[]{}->前者只能用在數組定義處,而后者可以傳參
                 可變參數列表,如int...args,String...args;可變參數列表使重載過程變的復雜了->如f(Integer...args);f(Long...args)->當調用f()的時候則編譯出錯,因為不知道該調用哪個f方法->可以給每個方法都就加上一個非可變參數->你應該總是只在方法的一個版本上使用可變參數列表,或者壓根就不是用它;
              7.enum
               枚舉是類,且有自己的方法;enum的名字能夠倍加清楚的表明程序意欲何為的;創建enum時,編譯器會自動添加一些有用的特性,如創建toString方法,很方便的顯示每個enum實例的名字;還會創建ordinal方法,表示某個特定enum常量的聲明順序;static values方法,用來按照enum常量的聲明順序,產生由這些常量構成的數組;與switch是絕佳的組合;
           直接將所得到的類型直接拿來使用,而不必過多的考慮,將enum用作另一種創建數據類型的方式;
           在枚舉之前,我們需要創建一個整型常量集,但是這些常量值并不會將其自身的取值限制在這個常量集的范圍內,因此顯的更有風險; 更難以使用;
            當然以前這樣的枚舉安全機制:(個人認為還是可以滿足需求的,只不過沒有一些編譯器添加的有用的特性,而且序列化的時候會有問題)
             public class Oriented
            {
             private int value;
             //兩個安全非final枚舉
             public static final Oriented ORI = new Oriented(1);
             public static final Oriented OR2  = new Oriendted(2);

             //私有構造函數
             private Oriented(int v)
             {
              value = v;
             }
            }
              8.垃圾回收器的確增加了運行時的開銷,而且Java解釋器從來就很慢;隨著時間推移,java在性能方面已經取得了長足的進步,不過速度問題仍然是它涉及某些編程領域的障礙.    
              9.部分源碼    

          package com.book.chap5.initAndDestroy;
          /**
           *
           *Finalize用法,驗證終結條件
           *<p>本例的終結條件是:所有的book對象在垃圾回收都應該checkin;main方法中,有一本書沒有被簽入,被finalize方法發現,輸出消息</p>
           *
           *@author landon
           *@since JDK1.6
           *@version 1.0 2012-4-12
           *
           
          */

          public class FinalizeUsage
          {
              
          public static void main(Stringargs)
              
          {
                  Book novel = new Book(true);
                  novel.checkIn();
                  
                  
          new Book(true);
                  
                  
          //強制進行終結動作[當然也可以通過重復的執行程序,假設程序將要分配大量的存儲空間,而導致垃圾回收動作的進行,最終也能找到錯誤的Book]
                  System.gc();
              }

          }


          class Book
          {
              
          private boolean checkOut;
              
              
          public Book(boolean checkOut)
              
          {
                  
          this.checkOut = checkOut;
              }

              
              
          /**
               * 檢入,書籍只有檢入后才可以被垃圾回收
               
          */

              
          public void checkIn()
              
          {
                  checkOut = false;
              }

              
              @Override
              
          protected void finalize()
              
          {
                  
          if(checkOut)
                  
          {
                      System.out.println("Error: has book checked out");
                      
          try
                      
          {
                          
          //調用父類的finalize方法
                          super.finalize();
                      }
           
                      
          catch (Throwable e)
                      
          {
                          e.printStackTrace();
                      }

                  }

              }

          }

                  

          package com.book.chap5.initAndDestroy;
          /**
           *
           *枚舉enum的初步用法
           *
           *@author landon
           *@since JDK1.6
           *@version 1.0 2012-4-12
           *
           
          */

          public class SimpleEnum
          {
              
          public static void main(Stringargs)
              
          {
                  Spiciness howHot = Spiciness.MEDIUM;
                  
          //打印枚舉,toString方法已實現
                  System.out.println(howHot);
                  
                  
          //ordinal按照聲明順序從0開始
                  for(Spiciness spiciness : Spiciness.values())
                  
          {
                      System.out.println(spiciness + " ordinal:" + spiciness.ordinal());
                  }

                  
                  testSwitchEnum(Spiciness.MILD);
                  testSwitchEnum(Spiciness.HOT);
                  testSwitchEnum(Spiciness.FLAMING);
              }

              
              
          //測試enum和switch的組合
              public static void testSwitchEnum(Spiciness spiciness)
              
          {
                  
          switch(spiciness)
                  
          {
                      
          //注意case必須是NOT必須是無限制的枚舉名稱[spiciness的類型已經確定是枚舉Spiciness,沒有必要特意加上Spiciness.NOT,畫蛇添足],而不是Spiciness.NOT,否則編譯報錯The qualified case label Spiciness.NOT must be replaced with the unqualified enum constant NOT
                      case NOT:
                          System.out.println("not");
                          
          break;
                      
          case MILD:
                          System.out.println("mild");
                          
          break;
                      
          case MEDIUM:
                          System.out.println("medium");
                          
          break;
                      
          case HOT:
                      
          case FLAMING:
                      
          default:
                          System.out.println("too hot");
                  }

              }

          }


          //枚舉聲明
          enum Spiciness
          {
              
          //常量,大寫
              NOT,MILD,MEDIUM,HOT,FLAMING
          }

           

          package com.book.chap5.initAndDestroy;
          /**
           *
           *可變參數
           *<p>可變參數列表可以使用任何類型的參數,包括基本類型</p>
           *
           *@author landon
           *@since JDK1.6
           *@version 1.0 2012-4-12
           *
           
          */

          public class VarArgs
          {
              
          public static void main(Stringargs)
              
          {
                  printArgsClass(1);
                  
                  
          //輸出class [I getClass,產生對象的類
                  System.out.println(new int[0].getClass());
                  
                  f(1,'a');
                  
          //The method f(float, Character[]) is ambig        uous for the type VarArgs
          //f('a','b');
              }

              
              
          public static void printArgsClass(intargs)
              
          {
                  System.out.println(args.getClass());
              }

              
              
          //重載的時候,使用可變參數列表一定要謹慎;非常有可能出現模棱兩可的調用->從而導致編譯報錯
              public static void f(float f,Characterargs)
              
          {
                  System.out.println(
          "first method");
              }

              
              
          public static void f(Characterargs)
              
          {
                  System.out.println(
          "second method");
              }

          }


          posted on 2013-01-08 17:04 landon 閱讀(1695) 評論(0)  編輯  收藏 所屬分類: Program 、Book
          主站蜘蛛池模板: 招远市| 乌拉特前旗| 司法| 丰县| 桃园市| 丰城市| 醴陵市| 明星| 名山县| 济阳县| 万宁市| 沧州市| 乌拉特前旗| 广河县| 嘉义市| 四川省| 湘潭市| 蒙城县| 响水县| 武清区| 东阳市| 新乐市| 西乡县| 潜江市| 行唐县| 化州市| 柳河县| 中山市| 满城县| 菏泽市| 怀柔区| 浦江县| 阆中市| 刚察县| 杨浦区| 鸡西市| 吉安县| 韶关市| 措勤县| 历史| 北安市|