Static Final Variables in Java – Java 中的静态最终变量

最后修改: 2023年 12月 12日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Simply put, static final variables, also called constants, are key features in Java to create a class variable that won’t change after initialization. However, in the case of a static final object reference, the state of the object may change.

简单地说,静态终局变量(也称为常量)是 Java 中创建初始化后不会更改的类变量的关键功能。但是,在 static final 对象引用的情况下,对象的状态可能会发生变化。

In this tutorial, we’ll learn how to declare and initialize constant variables. Also, we’ll discuss their usefulness.

在本教程中,我们将学习如何声明和初始化常量变量。此外,我们还将讨论它们的用处。

2. static final Variables

2.static final 变量

The static keyword associates a variable to a class itself, not to instances of the class.

static 关键字将变量与类本身关联,而不是与类的实例关联。

Furthermore, the final keyword makes a variable immutable. Its value can’t change after initialization.

此外,final 关键字使变量不可变。它的值在初始化后不会改变。

The combination of the two keywords helps create a constant. They are mostly named using uppercase and underscores to separate words.

这两个关键字的组合有助于创建一个常量。它们的命名大多使用大写字母和下划线来分隔单词

2.1. Initializing static final Variables

2.1.初始化 static final 变量

Here’s an example of how to declare a static final field and assign a value:

下面是一个如何声明 static final 字段并赋值的示例:

class Bike {
    public static final int TIRE = 2;
}

Here, we create a class named Bike with a constant class variable named TIRE and initialize it to two.

在这里,我们创建了一个名为 Bike 的类,其中包含一个名为 TIRE 的常量类变量,并将其初始化为 2。

Alternatively, we can initialize the variable via a static initializer block:

或者,我们可以通过 static 初始化块来初始化变量:

public static final int PEDAL;
static {
    PEDAL = 5;
}

This will compile without an error:

编译时不会出错:

@Test
void givenPedalConstantSetByStaticBlock_whenGetPedal_thenReturnFive() {
    assertEquals(5, Bike.PEDAL);
}

Here are some key rules for constant variables:

下面是一些关于常量变量的关键规则:

  • We must initialize upon declaration or in a static initializer block
  • We can’t reassign it after initialization

Attempting to initialize it outside the initialization scope will cause an exception.

在初始化范围之外尝试初始化会导致异常。

Also, we can’t initialize it via the constructor because constructors are invoked when we create an instance of a class. Static variables belong to the class itself and not to individual instances.

此外,我们不能通过构造函数对其进行初始化,因为构造函数是在我们创建类的实例时调用的。静态变量属于类本身,而不属于单个实例

2.2. static final Objects

2.2.静态 最终对象

We can also create static final object references:

我们还可以创建 static final 对象引用:

public static final HashMap<String, Integer> PART = new HashMap<>();

Since the PART reference is constant, it can’t be reassigned:

由于 PART 引用是常量,因此不能重新分配:

PART = new HashMap<>();

The code above throws an exception because we assign a new reference to an immutable variable.

上面的代码会产生异常,因为我们为不可变变量分配了一个新引用。

However, we can modify the state of the object:

不过,我们可以修改对象的状态:

@Test
void givenPartConstantObject_whenObjectStateChanged_thenCorrect() {
    Bike.PART.put("seat", 1);
    assertEquals(1, Bike.PART.get("seat"));
    Bike.PART.put("seat", 5);
    assertEquals(5, Bike.PART.get("seat"));
}

Here, we can change the value of the seat despite setting it to one initially. We mutate the contents of PART despite being a constant reference. Only the reference itself is immutable.

在这里,我们可以更改 seat 的值,尽管最初将其设置为 1。尽管 PART 是一个常量引用,但我们还是更改了它的内容。只有引用本身是不可变的。

Notably, the final keyword only makes primitive types, String, and other immutable types constant. In the case of an object, it only makes the reference constant, but the state of the object can be altered.

值得注意的是,final关键字只能使原始类型、String和其他不可变类型恒定。对于对象,它只使引用恒定,但对象的状态可以改变

3. Why Constants Are Useful

3.常数为何有用

Using static final variables has several advantages. It provides better performance since its values are inlined at compile time instead of a runtime value lookup.

使用 static final 变量有几个优点。它提供了更好的性能,因为其值是在编译时内联的,而不是在运行时查找

Moreover, declaring reusable values as constant avoids duplicating literals. Constant can be reused anywhere in the code, depending on the access modifier. A constant with a private access modifier will only be usable within the class.

此外,将可重复使用的值声明为常量可避免重复使用字面量。常量可以在代码的任何地方重复使用,这取决于 访问修饰符。带有 private 访问修饰符的常量只能在类中使用。

Additionally, a static final variable of primitive or String type is thread-safe. Its value remains unchanged when shared among multiple threads.

此外,基元或 String 类型的 static final 变量是线程安全的。它的值在多个线程共享时保持不变。

Finally, giving semantic names to constant values increases code readability. Also, it makes code self-documenting. For example, the java.math package provides constants like PI:

最后,为常量值赋予语义名称可以提高代码的可读性。此外,它还能使代码自文档化。例如,java.math 包提供了像 PI 这样的常量:

@Test
void givenMathClass_whenAccessingPiConstant_thenVerifyPiValueIsCorrect() {
    assertEquals(3.141592653589793, Math.PI);
}

The Math.PI encapsulates the mathematical constant value in a reusable way.

Math.PI以可重复使用的方式封装了数学常量值。

4. Conclusion

4.结论

In this article, we learned how to declare and initialize a constant variable. Also, we highlighted some of its use cases.

在本文中,我们学习了如何声明和初始化常量变量。此外,我们还重点介绍了常量变量的一些用例。

A final static variable defines a class-level constant. However, a static final object may still be mutable, even if the reference can’t change.

final static 变量定义了一个类级常量。不过,即使引用不能改变,final static 对象仍然可能是可变的。

As always, the complete source code for the examples is available over on GitHub.

一如既往,这些示例的完整源代码可在 GitHub 上获取。