實踐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
import java.awt.Point;
class PassByValue {
public static void modifyPoint(Point pt, int j) {
pt.setLocation(5, 5); // 1
j = 15;
System.out.println("During modifyPoint " + "pt = " + pt + " and j = " + j);
}
public static void main(String args[]) {
Point p = new Point(0, 0); // 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)。
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不能被改變,必須永遠指向同一個對象,但被指的那個對象可以隨意改變內部的屬性值。
關鍵字final 在Java中有多重用途,即可被用于instance變量、static變量,也可用于classes或methods,用于類,表示該類不能有子類;用于方法,表示該方法不允許被子類覆蓋。
array和Vector的比較
|
支持基本類型
|
支持對象
|
自動改變大小
|
速度快
|
array
|
Yes
|
Yes
|
No
|
Yes
|
Vector
|
No(1.5以上支持)
|
Yes
|
Yes
|
No
|
代碼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()。
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后,我們才能正確執行向下轉型,而不至于在運行期拋出異常。
posted on 2008-02-26 17:56
CoderDream 閱讀(302)
評論(0) 編輯 收藏 所屬分類:
學習筆記