# Java `static`关键字

原文：http://zetcode.com/java/statickeyword/

在本教程中，我们将讨论 Java 中的`static`关键字。 我们介绍了静态变量，方法，嵌套类，块和导入。

## Java `static`关键字定义

`static`关键字是不可访问的修饰符。 具有`static`修饰符的类型不属于类的实例； 它属于此类。 除此之外，`static`可用于创建类初始化器，常量，并且无需类限定即可导入静态变量。

## `static`关键字的用法

`static`关键字可以应用于：

*   变量
*   方法
*   块
*   嵌套类
*   导入

## Java 静态变量

静态变量也称为类变量。 一个类的所有实例共享一个静态变量的相同副本。 在执行开始时，它们仅初始化一次。 可以通过类名直接访问类变量，而无需创建实例。 `static`的一种常见用法是创建一个附加到类的常量值。

### 静态变量示例

`JavaStaticVariable.java`

```java
package com.zetcode;

import java.util.ArrayList;
import java.util.List;

class Being {

    public static int count;
}

class Cat extends Being {

    public Cat() {
        count++;
    }
}

class Dog extends Being {

    public Dog() {
        count++;
    }
}

class Donkey extends Being {

    public Donkey() {
        count++;
    }
}

public class JavaStaticVariable {

    public static void main(String[] args) {

        List<Being> beings = new ArrayList<>();

        beings.add(new Cat());
        beings.add(new Cat());
        beings.add(new Cat());
        beings.add(new Dog());
        beings.add(new Donkey());

        int nOfBeings = Being.count;

        System.out.format("There are %d beings %n", nOfBeings);
    }
}

```

在代码示例中，我们跟踪使用静态变量创建的生物。

```java
class Being {

    public static int count;
}

```

定义了一个静态变量。 该变量属于`Being`类，并由`Being`的所有实例（包括后代）共享。

```java
class Cat extends Being {

    public Cat() {
        count++;
    }
}

```

`Cat`类继承自`Being`。 它将增加`count`变量。

```java
class Dog extends Being {

    public Dog() {
        count++;
    }
}

```

`Dog`类增加相同的类变量。 因此，`Dog`和`Cat`指的是同一类变量。

```java
int nOfBeings = Being.count;

```

我们得到所有被创造的生物的数量。 我们通过类名称，后跟点运算符和变量名称来引用类变量。

### Java 静态变量属性

*   静态变量具有默认值。
*   静态变量可以通过静态和非静态方法直接访问。
*   静态变量称为类变量或静态字段。
*   静态变量与类关联，而不与任何对象关联。

## Java 静态方法

在没有对象实例的情况下调用静态方法。 要调用静态方法，我们使用类的名称，点运算符和方法的名称。 静态方法只能使用静态变量。 静态方法通常用于表示不会随对象状态变化的数据或计算。 例如，`java.lang.Math`包含用于各种计算的静态方法。

我们使用`static`关键字声明一个静态方法。 如果不存在`static`修饰符，则该方法称为实例方法。

### 静态方法限制

静态方法只能调用其他静态方法。 它们只能访问静态数据，而不能引用`this`和`super`。

### 静态方法示例

`JavaStaticMethod.java`

```java
package com.zetcode;

class Basic {

    static int id = 2321;

    public static void showInfo() {

        System.out.println("This is Basic class");
        System.out.format("The Id is: %d%n", id);
    }
}

public class JavaStaticMethod {

    public static void main(String[] args) {

        Basic.showInfo();
    }
}

```

在我们的代码示例中，我们定义了静态`ShowInfo()`方法。

```java
static int id = 2321;

```

静态方法只能使用静态变量。 静态变量不适用于实例方法。

```java
public static void showInfo() {

    System.out.println("This is Basic class");
    System.out.format("The Id is: %d%n", id);
}

```

这是我们的静态`ShowInfo()`方法。 它与静态`id`成员一起使用。

```java
Basic.showInfo();

```

要调用静态方法，我们不需要对象实例。 我们通过使用类的名称和点运算符来调用该方法。

## Java 静态`main()`方法

在 Java 控制台和 GUI 应用中，入口点具有以下特征：

```java
public static void main(String[] args)

```

通过声明`main()`方法`static`，运行时引擎可以调用它，而无需创建主类的实例。 由于`main()`的主要原因是要引导应用，因此不需要主类的实例。

另外，如果`main()`方法不是`static`，则将需要其他协定，例如默认构造器或主类的要求不能抽象。 因此，使用`static` `main()`方法是一种不太复杂的解决方案。

## Java 静态块

具有`static`修饰符的代码块称为类初始化器。 没有`static`修饰符的代码块是实例初始化器。 在加载类时，将按照定义的顺序（从上到下）执行类初始化器。

静态块在任何程序的生命周期中执行一次，没有其他方法可以调用它。

### 静态块示例

`JavaStaticBlock.java`

```java
package com.zetcode;

public class JavaStaticBlock {

    private static int i;

    static {

        System.out.println("Class initializer called");
        i = 6;
    }

    public static void main(String[] args) {

        System.out.println(i);
    }
}

```

这是静态初始化器的示例。

```java
static {

    System.out.println("Class initializer called");
    i = 6;
}

```

在静态初始化器中，我们将消息打印到控制台并初始化静态变量。

## Java 静态嵌套类

静态嵌套类是可以在没有封闭类实例的情况下创建的嵌套类。 它可以访问封闭类的静态变量和方法。

静态嵌套类可以在逻辑上对仅在一个地方使用的类进行分组。 它们增加了封装并提供了更具可读性和可维护性的代码。

### 静态嵌套类的限制

静态嵌套类无法调用非静态方法或访问封闭类实例的非静态字段。

### 静态嵌套类示例

`JavaStaticNestedClass.java`

```java
package com.zetcode;

public class JavaStaticNestedClass {

    private static int x = 5;

    static class Nested {

        @Override
        public String toString() {
            return "This is a static nested class; x:" + x;
        }
    }

    public static void main(String[] args) {

        JavaStaticNestedClass.Nested sn = new JavaStaticNestedClass.Nested();
        System.out.println(sn);
    }
}

```

该示例展示了一个静态的嵌套类。

```java
private static int x = 5;

```

这是`JavaStaticNestedClass`类的私有静态变量。 可以通过静态嵌套类访问它。

```java
static class Nested {

    @Override
    public String toString() {
        return "This is a static nested class; x:" + x;
    }
}

```

定义了一个静态的嵌套类。 它具有一种打印消息并引用静态`x`变量的方法。

```java
JavaStaticNestedClass.Nested sn = new JavaStaticNestedClass.Nested();

```

点运算符用于引用嵌套类。

## Java 静态导入

静态导入是 Java 5 中引入的一项功能，该功能允许在类中定义为`public static`的成员（字段和方法）在 Java 代码中使用，而无需指定定义该字段的类。

### 静态导入的缺点

过度使用静态导入功能会使我们的程序难以阅读和无法维护，并使用我们导入的所有静态成员污染其名称空间。

### 静态导入示例

`JavaStaticImport.java`

```java
package com.zetcode;

import static java.lang.Math.PI;

public class JavaStaticImport {

    public static void main(String[] args) {

        System.out.println(PI);
    }
}

```

在示例中，我们使用`PI`常量而不使用其类。

## Java 常量

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

```java
public static final double PI = 3.14159265358979323846;

```

例如，在`java.lang.Math`中，我们有一个名为`PI`的常数，其值是`π`的近似值（圆的周长与其直径之比）。

## 单例模式

单例设计模式可确保在应用的生命周期中构造一个且只有一个特定类的对象。

`Singleton.java`

```java
public class Singleton {    

    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
        return INSTANCE;
    }
}

```

在此简单的代码摘录中，我们对单个允许的对象实例具有内部静态引用。 我们通过静态方法访问对象。

在本教程中，我们介绍了 Java `static`关键字。 您可能也对相关教程感兴趣： [Java 中的`HashMap`迭代](/java/hashmapiterate/)， [Java8 `forEach`教程](/articles/java8foreach/)，[用 Java 阅读文本文件](/articles/javareadtext/)，[读写 Java 中的 ICO 图像](/articles/javaico/)， [Java 教程](/lang/java/)，[在 Java 中显示图像](/java/displayimage/)。