前面討論的this關鍵字,典型地反映了隨著對象引用的不同,其變量和操作亦不同,體現了面向對象編程的內涵。但是,有時在程序中的要求正好與此相反——需要代表整個類的數據。Java提供的靜態數據(static data)就是專門用來實現這一要求的。
二、類數據
靜態數據屬于全體對象,是所有對象共享的數據,或類數據。靜態常量也稱為類常量;靜態變量也稱類變量。在解決實際問題中經常會遇到類數據。例如,Math.PI,Math.E對所有對象的算術運算都是一樣的,它們被定義為Math類的靜態常量。
再例如,稅收比率在計算稅款時對所有定義的對象都適用,也是靜態數據的典型例子。有時,我們需要統計創建了多少個對象,或者有多少個對象調用了某個方法,或者應用了某個操作等等,這需要在程序中使用靜態數據來完成這些任務。類數據可以是private或public。
如下是定義靜態數據的典型例子。
例1.定義靜態變量。
private static double accountLimit; //定義一個雙精度靜態變量
private static int userCount = 0; //定義一個整數靜態變量并賦值
public static String welcome = "Java is hot!"; //定義一個字符串靜態變量并賦值
例2.定義靜態常量。
private static final float TAX_RATE = 0.0875f; //定義一個浮點靜態常量
public static final double EARTH_MASS = 5.972e24; //定義一個雙精度靜態常量
public static final int MONTH_IN_YEAR = 12; //定義一個整數靜態常量
注意 靜態常量必須在定義時賦值。否則為非法。
如下是使用靜態數據的典型例子:
public FutureValue() { //構造器
//對對象數據初始化的各語句
...
userCount++; //每創建一個對象,都對原來統計用戶數目的靜態變量userCount加1
}
public FutureValue(String name) {
this.name = name;
//對其他各變量初始化的語句
...
userCount++; //同上
}
以上例子表示無論以哪個構造器創建對象,對靜態變量userCount都執行加1,達到統計對象的目的。如果執行下列輸出語句:
System.out.println(myFutureValue.getUserCount()); //用對象調用
其輸出值與:
System.out.pritnln(FutureValue.getUserCount()); //用靜態方法通過類直接調用
完全一樣。
靜態數據通常由靜態方法來調用。
三、 屬于所有對象
靜態數據為什么屬于整個類,或類中的所有對象呢?這是因為它們被儲存在特殊指定的存儲器中。進一步講,靜態數據儲存在類訪問區的儲存空間。這個儲存空間是這個類代表的所有對象共享的,它的訪問生命期和這個類相同。
而實例數據分別儲存在代表每個對象的一段存儲區域中。假設我們創建了100個對象,那么將有100個這樣的儲存區域存在。即每個對象都有它自己獨立存儲區域,用來存儲它所具有的所有實例數據。這個存儲區域的訪問生命期和對象相同。
四、靜態數據原則
靜態數據是類的組成部分,確定靜態數據首先從類的設計入手,分析和確定類的應用范疇,它所執行的運算和操作,包括確定數學公式以及運算邏輯等。由此來確定靜態數據和實例數據。靜態數據與實例數據本質的不同在于:
(1) 實例數據是在這個類的應用中,每個對象,或大多數對象都具有的、但各自有不同值的數據。例如,在計算投資回報的程序中,每個對象都有姓名(name)、月投資額(monthlyInvest),年投資回報率(yearlyRate),以及投資年(years),但這些數據的值對每個對象來說,是完全由對象來確定的,與整個類無關;與具體對象的形態有關。
(2) 靜態數據是所有對象共享的數據。在這個類的應用中,無論哪一個對象,如果應用這個數據的話,都必須具有相同的值,或者這個數據對所有對象都有意義,或者這個數據代表了所有對象的形態表征,與整個類有關。
根據以上分析,確定靜態數據可根據如下原則:
1. 對類中的對象進行統計的數據應該確定為靜態數據。
2. 對類中所有對象,設置上下限的數據,應該確定為靜態常量數據。
3. 在執行運算的公式和解決問題的邏輯中,某個常量對類中所有的對象,如果有相同應用,這個常量應該確定為靜態常量數據。
4. 用來對類中所有對象進行提示、詢問、問候以及其他與具體對象無關的信息或數據,應該確定為靜態常量數據。