前面讨论的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. 用来对类中所有对象进行提示、询问、问候以及其他与具体对象无关的信息或数据,应该确定为静态常量数据。