java中静态常量的编写方式_Java 静态字段与静态方法(学习 Java 编程语言 031)...

1. 静态字段

静态字段就是将字段定义为 static 的字段,类的所有实例共享一个静态字段。静态字段属于类,而不属于任何单个对象。而对于非静态的实例字段,每个对象都有自己的一个副本。

class Employee

{

private static int nextId = 1;

private int id;

...

}

现在,每个 Employee 对象都一个自己的 id 字段,但 Employee 类的所有实例将共享一个 nextId 字段。即使没有 Employee 对象,静态字段 nextId 也存在。它属于类,而不属于任何单个对象。

2. 静态常量

静态变量使用得比较少,但静态常量却很常用。例如,在 Math 类中定义了一个静态常量。

public final class Math {

...

public static final double PI = 3.14159265358979323846;

...

}

在程序中,可以用 Math.PI 来访问这个常量。

如果省略关键字 static,PI 就变成了 Math 类的一个实例字段。也就是说,需要通过 Math 类的一个对象来访问 PI,并且每一个 Math 对象都有它自己的一个 PI 副本。

另一个静态常量是 System.out。在 System 类中声明如下:

public final class System {

...

public static final PrintStream out = null;

...

}

由于每个类对象都可以修改公共字段,所以,最好不要有公共字段。然而,公共常量(即 final 字段)却没有问题。因此 out 被声明为 final,所以,不允许再将它重新赋值为另一个打印流:

System.out = new PrintStream(...); // 错误,out 是 final 常量

注释: 如果查看 System 类,就会发现有一个 setOut 方法可以将 System.out 设置为不同的流。你可能会感到奇怪,为什么这个方法可以修改 final 变量的值。原因在于,setOut 方法是一个原生方法,而不是在 Java 语言中实现的。原生方法可以绕过 Java 语言的访问控制机制。这是一种特殊的解决方案,在自己编写程序时不要模仿这种做法。

3. 静态方法

静态方法是不在对象上执行的方法。例如,Math 类的 pow 方法就是一个静态方法。表达式:

Math.pow(x, a)

会计算幂 xa。在完成计算时,它并不使用任何 Math 对象。换句话说,它没有隐式参数。

可以认为静态方法是没有 this 参数的方法(在一个非静态的方法中,this 参数指示这个方法的隐式参数)。

静态方法不能访问实例字段,因为静态方法不能在对象上执行操作。但是,静态方法可以访问静态字段。

class Employee

{

private static int nextId = 1;

private int id;

public static int getNextId(){

return nextId; // 返回静态字段

}

...

}

可以提供类名来调用这个方法:

int n = Employee.getNextId();

注释:可以使用对象调用静态方法,这是合法的。例如,如果 harry 是一个 Employee 对象,可以使用 harry.getNextId() 替代 Employee.getNextId()。不过,这种方式很容易造成混淆,其原因是 getNextId 方法计算的结果与 harry 毫无关系。我们建议使用类名而不是对象来调用静态方法。

在下面两种情况下使用静态方法:

方法不需要访问对象状态,因为它需要的所有参数都通过显示参数提供(例如,Math.pow)。

方法只需要访问类的静态字段(例如:Employee.getNextId())。

4. 工厂方法

静态方法还有另外一种常见的用途。类似 LocalDate 和 NumberFormat 的类使用静态工厂方法(factory method)来构造对象。例如工厂方法 LocalDate.now 和 LocalDate.of。NumberFormat 类如下生成不同风格的格式化对象。

NumberFormat currencyFormatter = NumberFormat.getCurrencyInstance();

NumberFormat percentFormatter = NumberFormat.getPercentInstance();

double x = 0.1;

System.out.println(currencyFormatter.format(x)); // prints ¥0.10

System.out.println(percentFormatter.format(x)); // prints 10%

NumberFormat 类不利用构造器完成这些操作的两个主要原因:

无法命名构造器,构造器的名字必须与类名相同。但是,这里希望有两个不同的名字,分别得到货币实例和百分比实例。

使用构造器时,无法改变所构造对象的类型。而工厂方法实际上将返回 DecimalFormat 类的对象,这是 NumberFormat 的子类。

5. main 方法

可以调用静态方法而不需要任何对象。例如,不需要构造 Math 类的任何对象,就可以调用 Math.pow。

main 方法是一个静态方法。

public class Application {

public static void main(String[] args) {

// 在这里构造对象

}

}

main 方法不对任何对象进行操作。事实上,在启动程序时还没有任何一个对象。静态 main 方法将执行并构造程序所需要的对象。

每一个类可以有一个 main 方法。这是常用于对类进行单元测试的一个技巧。

6. 其他 API

java.util.Objects 7

static <T> void requireNonNull(T obj)

如果 obj 为 null,会抛出一个 NullPointerException 异常而没有抛出消息。

static <T> void requireNonNull(T obj, Strimg message)

如果 obj 为 null,会抛出一个 NullPointerException 异常而抛出给定消息。

static <T> void requireNonNull(T obj, Supplier<Strimg> messageSupplier)

如果 obj 为 null,会抛出一个 NullPointerException 异常而抛出给定消息。

static <T> T requireNonNullElse(T obj, T defaultObj)

如果 obj 不为 null 则返回 obj,或者如果 obj 为 null 则返回默认对象。

static <T> T requireNonNullElseGet(T obj, Supplier<T> defaultSupplier)

如果 obj 不为 null 则返回 obj,或者如果 obj 为 null 则返回默认对象。


版权声明:本文为weixin_30984001原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。