從制造到創造
          軟件工程師成長之路
          posts - 292,  comments - 96,  trackbacks - 0
          實踐1:參數以by value方式而非by reference方式傳遞
          實踐2:對不變的data和object reference使用final
          實踐3:缺省情況下所有non-static函數都可被重寫
          實踐4:在array和Vectors之間慎重選擇
          實踐5:多態(polymorphism)優于instanceof
          實踐6:必要時才使用instanceof
          實踐7:一旦不需要object reference,就將它設為null

          實踐1:參數以by value方式而非by reference方式傳遞

          import java.awt.Point;

          class PassByValue {
              
          public static void modifyPoint(Point pt, int j) {
                  pt.setLocation(
          55); // 1
                  j = 15;
                  System.out.println(
          "During modifyPoint " + "pt = " + pt + " and j = " + j);
              }

              
          public static void main(String args[]) {
                  Point p 
          = new Point(00); // 2
                  int i = 10;
                  System.out.println(
          "Before modifyPoint " + "p  = " + p + " and i = " + i);
                  modifyPoint(p, i); 
          // 3
                  System.out.println("After  modifyPoint " + "p  = " + p + " and i = " + i);
              }
          }
          這段代碼在//2處建立了一個Point對象并設初值為(0,0),接著將其值賦予object reference 變量p。然后對基本類型int i賦值10。//3調用static modifyPoint(),傳入p和i。modifyPoint()對第一個參數pt調用了setLocation(),將其左邊改為(5,5)。然后將第二個參數j賦值為15.當modifyPoint()返回的時候,main()打印出p和i的值。

          程序輸出如下:
          Before modifyPoint p  = java.awt.Point[x=0,y=0] and i = 10
          During modifyPoint pt 
          = java.awt.Point[x=5,y=5] and j = 15
          After   modifyPoint p  
          = java.awt.Point[x=5,y=5] and i = 10

          這顯示modifyPoint()改變了//2 所建立的Point對象,卻沒有改變int i。在main()之中,i被賦值10.由于參數通過by value方式傳遞,所以modifyPoint()收到i的一個副本,然后它將這個副本改為15并返回。main()內的原值i并沒有受到影響。

          對比之下,事實上modifyPoint() 是在與“Point 對象的 reference 的復件”打交道,而不是與“Point對象的復件”打交道。當p從main()被傳入modifyPoint()時,傳遞的是p(也就是一個reference)的復件。所以modifyPoint()是在與同一個對象打交道,只不過通過別名pt罷了。在進入modifyPoint()之后和執行 //1 之前,這個對象看起來是這樣:

          所以//1 執行以后,這個Point對象已經改變為(5,5)。

          實踐2:對不變的data和object reference使用final

          Java 關鍵字 final 用來表示常量數據。例如:

          public class Test {
              
          static final int someInt = 10;
              
          // 
          }

          這段代碼聲明了一個 static 類變量,命名為 someInt,并設其初值為10。
          任何試圖修改 someInt 的代碼都將無法通過編譯。例如:

              // 
              someInt = 9// Error
              
          // 

          關鍵字 final 可防止 classes 內的 instance 數據遭到無意間的修改。如果我們想要一個常量對象,又該如何呢?例如:

          class Circle {
              
          private double rad;

              
          public Circle(double r) {
                  rad 
          = r;
              }

              
          public void setRadius(double r) {
                  rad 
          = r;
              }

              
          public double radius() {
                  
          return rad;
              }
          }

          public class FinalTest {
              
          private static final Circle wheel = new Circle(5.0);

              
          public static void main(String args[]) {
                  System.out.println(
          "Radius of wheel is " + wheel.radius());
                  wheel.setRadius(
          7.4);
                  System.out.println(
          "Radius of wheel is now " + wheel.radius());
              }
          }

          這段代碼的輸出是:

          Radius of wheel is 5.0
          Radius of wheel is now 
          7.4

          在上述第一個示例中,我們企圖改變final 數據值時,編譯器會偵測出錯誤。
          在第二個示例中,雖然代碼改變了 instance變量wheel的值,編譯器還是讓它通過了。我們已經明確聲明wheel為final,它怎么還能被改變呢?
          不,我們確實沒有改變 wheel 的值,我們改變的是wheel 所指對象的值。wheel 并無變化,仍然指向(代表)同一個對象。變量wheel是一個 object reference,它指向對象所在的heap位置。有鑒如此,下面的代碼會怎樣?

          public class FinalTest {
              
          private static final Circle wheel = new Circle(5.0);

              
          public static void main(String args[]) {
                  System.out.println(
          "Radius of wheel is " + wheel.radius());
                  wheel 
          = new Circle(7.4); // 1
                  System.out.println(
          "Radius of wheel is now " + wheel.radius());
              }
          }

          編譯代碼,// 1 處出錯。由于我們企圖改變 final 型變量 wheel 的值,所以這個示例將產生編譯錯誤。換言之,代碼企圖令wheel指向其他對象。變量wheel是final,因此也是不可變的。它必須永遠指向同一個對象。然而wheel所指向的對象并不受關鍵字final的影響,因此是可變的。

          關鍵字 final 只能防止變量值的改變。如果被聲明為 final 的變量是個 object reference,那么該reference不能被改變,必須永遠指向同一個對象,但被指的那個對象可以隨意改變內部的屬性值。

          實踐3:缺省情況下所有non-static函數都可以被覆蓋重寫

          關鍵字final 在Java中有多重用途,即可被用于instance變量、static變量,也可用于classes或methods,用于類,表示該類不能有子類;用于方法,表示該方法不允許被子類覆蓋。

          實踐4:在array和vectors之間慎重選擇

          array和Vector的比較

           

          支持基本類型

          支持對象

          自動改變大小

          速度快

          array

          Yes

          Yes

          No

          Yes

          Vector

          No(1.5以上支持)

          Yes

          Yes

          No

          實踐5:多態(polymorphism)優于instanceof

          代碼1:instanceof方式

          interface Employee {
              
          public int salary();
          }

          class Manager implements Employee {
              
          private static final int mgrSal = 40000;

              
          public int salary() {
                  
          return mgrSal;
              }
          }

          class Programmer implements Employee {
              
          private static final int prgSal = 50000;
              
          private static final int prgBonus = 10000;

              
          public int salary() {
                  
          return prgSal;
              }

              
          public int bonus() {
                  
          return prgBonus;
              }
          }

          class Payroll {
              
          public int calcPayroll(Employee emp) {
                  
          int money = emp.salary();
                  
          if (emp instanceof Programmer)
                      money 
          += ((Programmer) emp).bonus(); // Calculate the bonus
                  return money;
              }

              
          public static void main(String args[]) {
                  Payroll pr 
          = new Payroll();
                  Programmer prg 
          = new Programmer();
                  Manager mgr 
          = new Manager();
                  System.out.println(
          "Payroll for Programmer is " + pr.calcPayroll(prg));
                  System.out.println(
          "payroll for Manager is " + pr.calcPayroll(mgr));
              }
          }
          依據這個設計,calcPayroll()必須使用instanceof操作符才能計算出正確結果。因為它使用了Employee接口,所以它必須斷定Employee對象究竟實際屬于哪個class。程序員有獎金而經理沒有,所以你必須確定Employee對象的運行時類型。

          代碼2:多態方式
          interface Employee {
              
          public int salary();

              
          public int bonus();
          }

          class Manager implements Employee {
              
          private static final int mgrSal = 40000;
              
          private static final int mgrBonus = 0;

              
          public int salary() {
                  
          return mgrSal;
              }

              
          public int bonus() {
                  
          return mgrBonus;
              }
          }

          class Programmer implements Employee {
              
          private static final int prgSal = 50000;
              
          private static final int prgBonus = 10000;

              
          public int salary() {
                  
          return prgSal;
              }

              
          public int bonus() {
                  
          return prgBonus;
              }
          }

          class Payroll {
              
          public int calcPayroll(Employee emp) {
                  
          // Calculate the bonus. No instanceof check needed.
                  return emp.salary() + emp.bonus();
              }

              
          public static void main(String args[]) {
                  Payroll pr 
          = new Payroll();
                  Programmer prg 
          = new Programmer();
                  Manager mgr 
          = new Manager();
                  System.out.println(
          "Payroll for Programmer is " + pr.calcPayroll(prg));
                  System.out.println(
          "Payroll for Manager is " + pr.calcPayroll(mgr));
              }
          }
          在這個設計中,我們為Employee接口增加了 bonus(),從而消除了instanceof的必要性。實現Employee接口的兩個 classes:Programmer和Manager,都必須實現salary()和bonus()。這些修改顯著簡化了calcPayroll()。


          實踐6:必要時才使用instanceof

          import java.util.Vector;

          class Shape {
          }

          class Circle extends Shape {
              
          public double radius() {
                  
          return 5.7;
              }
              
          // 
          }

          class Triangle extends Shape {
              
          public boolean isRightTriangle() {
                  
          // Code to determine if triangle is right
                  return true;
              }
              
          // 
          }

          class StoreShapes {
              
          public static void main(String args[]) {
                  Vector shapeVector 
          = new Vector(10);
                  shapeVector.add(
          new Triangle());
                  shapeVector.add(
          new Triangle());
                  shapeVector.add(
          new Circle());
                  
          // 
                  
          // Assume many Triangles and Circles are added and removed
                  
          // 
                  int size = shapeVector.size();
                  
          for (int i = 0; i < size; i++) {
                      Object o 
          = shapeVector.get(i);
                      
          if (o instanceof Triangle) {
                          
          if (((Triangle) o).isRightTriangle()) {
                              
          // 
                          }
                      } 
          else if (o instanceof Circle) {
                          
          double rad = ((Circle) o).radius();
                          
          // 
                      }
                  }
              }
          }
          這段代碼表明在 這種場合下 instanceof 操作符是必需的。當程序從Vector 取回對象,它們屬于java.lang.Object。利用instanceof確定對象實際屬于哪個class后,我們才能正確執行向下轉型,而不至于在運行期拋出異常。

          實踐7:一旦不再需要object reference,就將它設為null

          posted on 2008-02-26 17:56 CoderDream 閱讀(303) 評論(0)  編輯  收藏 所屬分類: 學習筆記

          <2008年2月>
          272829303112
          3456789
          10111213141516
          17181920212223
          2425262728291
          2345678

          常用鏈接

          留言簿(9)

          我參與的團隊

          隨筆分類(245)

          隨筆檔案(239)

          文章分類(3)

          文章檔案(3)

          收藏夾(576)

          友情鏈接

          搜索

          •  

          積分與排名

          • 積分 - 458376
          • 排名 - 114

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 黄冈市| 嘉祥县| 景泰县| 五大连池市| 息烽县| 江城| 宝清县| 罗源县| 潍坊市| 新兴县| 铜鼓县| 台前县| 牙克石市| 定兴县| 永顺县| 穆棱市| 多伦县| 惠来县| 南丰县| 永年县| 长沙县| 武邑县| 大埔县| 花莲市| 上杭县| 和政县| 乐平市| 中牟县| 汉阴县| 横山县| 凌海市| 万年县| 崇义县| 南阳市| 东至县| 吴江市| 吴桥县| 乌苏市| 江油市| 惠安县| 抚顺市|