在本节中,我们讨论如何使用static关键字来创建属于该类而不是该类实例的字段和方法

类变量

从相同的类蓝图创建多个对象时,它们每个都有各自不同的实例变量副本。在Bicycle类中,实例变量是cadencegearspeed。每个Bicycle对象对于这些变量都有其自己的值,存储在不同的位置里面。
有时,您希望拥有所有对象共有的变量。这可以通过static修饰符完成。声明中带有static修饰符的字段称为静态字段类变量它们与类关联,而不与任何对象关联。该类的每个实例共享一个类变量,该变量位于内存中的一个固定位置。任何对象都可以更改类变量的值,但是也可以在不创建类实例的情况下操纵类变量。
例如,假设您要创建多个Bicycle对象并为每个对象分配一个序列号,第一个对象以1开头。ID号对每个对象都是唯一的,因此是一个实例变量。同时,您需要一个字段来跟踪已创建的Bicycle对象数,以便知道要分配给下一个对象的ID。这样的字段与任何单个对象都不相关,而与整个类相关。为此,您需要一个类变量numberOfBicycles,如下所示:
public class Bicycle {
private int cadence;
private int gear;
private int speed;

  1. // **add an instance variable for the object ID**<br /> private int id;
  2. // **add a class variable for the**<br /> // **number of Bicycle objects instantiated**<br /> private **static** int numberOfBicycles = 0;<br /> ...<br />}<br />**类变量由类名本身引用**,如
  1. Bicycle.numberOfBicycles

这清楚表明它们是类变量。


注意: 您还可以使用对象引用来引用静态字段,例如

  1. myBike.numberOfBicycles

但是不建议这样做,因为它并不能清楚地表明它们是类变量。


您可以使用Bicycle构造函数来设置实例变量id并增加类变量numberOfBicycles
public class Bicycle {
private int cadence;
private int gear;
private int speed;
private int id;
private static int numberOfBicycles = 0;

public Bicycle(int startCadence, int startSpeed, int startGear){
gear = startGear;
cadence = startCadence;
speed = startSpeed;

  1. // **increment number of Bicycles**<br /> // **and assign ID number**<br /> **id = ++numberOfBicycles;**<br /> }
  2. // **new method to return the ID instance variable**<br /> public int getID() {<br /> return id;<br /> }<br /> ...<br />}

类方法

Java编程语言支持静态方法以及静态变量。静态方法的声明中带有static修饰符,应使用类名调用它们,而无需创建该类的实例,

  1. ClassName.methodName(args)

注意: 您还可以使用对象引用来引用静态方法,例如

  1. instanceName.methodName(args)

但这是不鼓励的,因为这并不清楚表示它们是类方法。


静态方法的常见用法是访问静态字段。例如,我们可以在Bicycle类中添加一个静态方法来访问静态字段numberOfBicycles
public static int getNumberOfBicycles() {
return numberOfBicycles;
}
并非所有的实例和类变量以及方法的允许组合:

  • 实例方法可以直接访问实例变量和实例方法。
  • 实例方法可以直接访问类变量和类方法。
  • 类方法可以直接访问类变量和类方法。
  • 类方法不能直接访问实例变量或实例方法,它们必须使用对象引用。同样,类方法不能使用this关键字,因为没有实例可供this引用。

    常数

    static修饰符,和final修饰符的组合,也可以用来定义常量。final修饰符表明这个字段的值不能改变。
    例如,以下变量声明定义了一个名为PI的常量,其值近似为pi(圆的周长与其直径之比):
    1. static final double PI = 3.141592653589793;
    不能重新分配以这种方式定义的常量,如果您的程序尝试这样做,则是编译时错误。按照约定,常量值的名称用大写字母拼写。如果名称由多个单词组成,则单词之间用下划线(_)分隔。

注意: 如果将基本类型或字符串定义为常量,并且在编译时知道该值,则编译器会使用其值替换代码中各处的常量名称。这称为编译时常量。如果外界的常数值发生了变化(例如,如果pi实际应为3.975,则需要合法),则您将需要重新编译使用该常数的任何类以获取当前值。


Bicycle

经过本节的所有修改后,Bicycle类现在为:

  1. public class Bicycle {
  2. private int cadence;
  3. private int gear;
  4. private int speed;
  5. private int id;
  6. private static int numberOfBicycles = 0;
  7. public Bicycle(int startCadence,
  8. int startSpeed,
  9. int startGear) {
  10. gear = startGear;
  11. cadence = startCadence;
  12. speed = startSpeed;
  13. id = ++numberOfBicycles;
  14. }
  15. public int getID() {
  16. return id;
  17. }
  18. public static int getNumberOfBicycles() {
  19. return numberOfBicycles;
  20. }
  21. public int getCadence() {
  22. return cadence;
  23. }
  24. public void setCadence(int newValue) {
  25. cadence = newValue;
  26. }
  27. public int getGear(){
  28. return gear;
  29. }
  30. public void setGear(int newValue) {
  31. gear = newValue;
  32. }
  33. public int getSpeed() {
  34. return speed;
  35. }
  36. public void applyBrake(int decrement) {
  37. speed -= decrement;
  38. }
  39. public void speedUp(int increment) {
  40. speed += increment;
  41. }
  42. }