# 了解类成员

> 原文： [https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html](https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html)

在本节中，我们将讨论使用`static`关键字创建属于该类的字段和方法，而不是类的实例。

## 类变量

当从同一个类蓝图创建许多对象时，它们每个都有自己不同的 _ 实例变量 _ 副本。在`Bicycle`类的情况下，实例变量是`cadence`，`gear`和`speed`。每个`Bicycle`对象都有自己的这些变量值，存储在不同的内存位置。

有时，您希望拥有所有对象共有的变量。这是通过`static`修饰符完成的。在声明中具有`static`修饰符的字段称为 _ 静态字段 _ 或 _ 类变量 _。它们与类相关联，而不是与任何对象相关联。该类的每个实例共享一个类变量，该变量位于内存中的一个固定位置。任何对象都可以更改类变量的值，但也可以在不创建类实例的情况下操作类变量。

例如，假设您要创建多个`Bicycle`对象并为每个对象分配序列号，从第一个对象开始为 1。此 ID 号对每个对象都是唯一的，因此是一个实例变量。同时，您需要一个字段来跟踪已创建的`Bicycle`对象的数量，以便您知道要分配给下一个对象的 ID。这样的字段与任何单个对象无关，而与整个类无关。为此，您需要一个类变量`numberOfBicycles`，如下所示：

```
public class Bicycle {

    private int cadence;
    private int gear;
    private int speed;

    // add an instance variable for the object ID
    private int id;

    // add a class variable for the
    // number of Bicycle objects instantiated
    private static int numberOfBicycles = 0;
        ...
}

```

类变量由类名本身引用，如

```
Bicycle.numberOfBicycles

```

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

* * *

**Note:** You can also refer to static fields with an object reference like

```
myBike.numberOfBicycles

```

but this is discouraged because it does not make it clear that they are class variables.

* * *

您可以使用`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;

        // increment number of Bicycles
        // and assign ID number
        id = ++numberOfBicycles;
    }

    // new method to return the ID instance variable
    public int getID() {
        return id;
    }
        ...
}

```

## 分类方法

Java 编程语言支持静态方法和静态变量。静态方法在其声明中具有`static`修饰符，应该使用类名调用，而不需要创建类的实例，如

```
ClassName.methodName(args)

```

* * *

**Note:** You can also refer to static methods with an object reference like

```
instanceName.methodName(args)

```

but this is discouraged because it does not make it clear that they are class methods.

* * *

静态方法的常见用途是访问静态字段。例如，我们可以向`Bicycle`类添加一个静态方法来访问`numberOfBicycles`静态字段：

```
public static int getNumberOfBicycles() {
    return numberOfBicycles;
}

```

并非所有实例和类变量和方法的组合都是允许的：

*   实例方法可以直接访问实例变量和实例方法。
*   实例方法可以直接访问类变量和类方法。
*   类方法可以直接访问类变量和类方法。
*   类方法**不能**直接访问实例变量或实例方法 - 它们必须使用对象引用。此外，类方法不能使用`this`关键字，因为没有`this`引用的实例。

## 常量

`static`修饰符与`final`修饰符结合使用，也用于定义常量。 `final`修饰符表示此字段的值不能更改。

例如，以下变量声明定义了一个名为`PI`的常量，其值是 pi 的近似值（圆周长与直径的比值）：

```
static final double PI = 3.141592653589793;

```

以这种方式定义的常量不能重新分配，如果您的程序尝试这样做，则它是编译时错误。按照惯例，常量值的名称拼写为大写字母。如果名称由多个单词组成，则单词由下划线（_）分隔。

* * *

**Note:** If a primitive type or a string is defined as a constant and the value is known at compile time, the compiler replaces the constant name everywhere in the code with its value. This is called a _compile-time constant_. If the value of the constant in the outside world changes (for example, if it is legislated that pi actually should be 3.975), you will need to recompile any classes that use this constant to get the current value.

* * *

## `Bicycle`类

在本节中进行了所有修改之后，`Bicycle`类现在是：

```
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;

        id = ++numberOfBicycles;
    }

    public int getID() {
        return id;
    }

    public static int getNumberOfBicycles() {
        return numberOfBicycles;
    }

    public int getCadence() {
        return cadence;
    }

    public void setCadence(int newValue) {
        cadence = newValue;
    }

    public int getGear(){
        return gear;
    }

    public void setGear(int newValue) {
        gear = newValue;
    }

    public int getSpeed() {
        return speed;
    }

    public void applyBrake(int decrement) {
        speed -= decrement;
    }

    public void speedUp(int increment) {
        speed += increment;
    }
}

```