7.4 static关键字

  在通常情况下,要使用一个类对象(实例)的公有成员变量,需要通过这个类实例化出对象,再通过“对象名.变量名”的形式访问。作为程序员,有时需要定义一个类级别的变量,它的使用完全独立于该类的任何对象,可以直接通过“类名.变量名”的形式进行访问。

  在类成员的声明前,加上static(静态的)关键字,就能创建出这样的静态类成员。static成员最常见的例子是main方法。因为在程序开始执行时必须调用main方法,所以将它声明为static。

  声明为static的变量称为静态变量或类变量。可以直接通过类名引用静态变量,也可以通过实例名来引用静态变量,但最好采用前者,因为采用后者容易混淆静态变量和实例变量。静态变量是跟类相关联的,类的所有实例共同拥有一个静态变量。

  声明为static的方法称为静态方法或类方法。静态方法可以直接调用静态方法,访问静态变量,但是不能直接访问实例变量和实例方法。静态方法中不能使用this关键字,因为静态方法不属于任何一个实例。

7.4.1 static关键字的使用

1.用static修饰类的成员变量

  用static修饰的类的成员变量是静态变量,对该类的所有实例来说,只有一个静态值存在,所有实例共用一个变量。静态变量是指不管类实例化出多少个对象,系统仅在第一次调用类的时候为静态变量分配内存。先来看下面的例子。

  1. public class TestStatic
  2. {
  3. public static void main(String[] args)
  4. {
  5. Student wangYun = new Student();
  6. wangYun.avgAge = 22; //将Student类变量的值设置为22
  7. System.out.println("王云所在班平均年龄为:" + wangYun.avgAge);
  8. Student liuJT = new Student();
  9. liuJT.avgAge = 21; //将Student类变量的值设置为21
  10. System.out.println("王云所在班平均年龄为:" + wangYun.avgAge);
  11. System.out.println("刘静涛所在班平均年龄为:" + liuJT.avgAge);
  12. }
  13. }
  14. class Student
  15. {
  16. public static int avgAge; //类变量,存放平均年龄
  17. }

  程序运行结果如图7.10所示。

7.4 static关键字 - 图1
图7.10 类变量使用

  通过程序运行结果可以看出,所有Sutdent类的实例wangYun和liuJT都共用了静态变量avgAge,当给其中任何一个实例的静态变量赋值,都是对这一个静态变量进行操作。

2.用static修饰类的成员方法

  用static修饰类的成员方法表示,该方法被绑定于类本身,而不是类的实例。看下面的例子。

  1. public class TestStatic2
  2. {
  3. public static void main(String[] args)
  4. {
  5. Student.showAvgAge(); //调用静态方法
  6. System.out.println("静态变量输出所在班平均年龄为:" + Student.avgAge);
  7. }
  8. }
  9. class Student
  10. {
  11. public static int avgAge = 22; //类变量,存放平均年龄
  12. public static void showAvgAge() //静态方法输出班平均年龄
  13. {
  14. System.out.println("静态方法输出所在班平均年龄为:22");
  15. }
  16. }

  程序运行结果如图7.11所示。

7.4 static关键字 - 图2
图7.11 静态方法使用

  注意,在TestStatic2程序的main方法中,都是通过“类名.静态变量名”和“类名.静态方法名”的形式访问静态变量和调用静态方法的。通过“类实例.静态变量”和“类实例.静态方法”也可以访问静态变量和调用静态方法,但不推荐使用。

3.静态方法不能操作实例变量

  静态方法可以操作静态变量,不能操作实例变量,可以通过下面的例子看出。

  1. public class Student
  2. {
  3. public int avgAge = 22; //实例变量,存放平均年龄
  4. public static void showAvgAge() //静态方法调用实例变量——编译出错
  5. {
  6. System.out.println("静态方法输出所在班平均年龄为:" + avgAge);
  7. }
  8. }

  编译时报错,如图7.12所示。

7.4 static关键字 - 图3
图7.12 静态方法调用实例变量

7.4.2 Java静态块

  第6章学习了对象的初始化过程,在使用new关键字创建并初始化对象的过程中,具体的初始化分为以下4步。

  (1)给对象的实例变量分配空间,默认初始化成员变量。

  (2)成员变量声明时的初始化。

  (3)初始化块初始化。

  (4)构造方法初始化。

  接下来将会先介绍什么是Java静态块,并结合对象的初始化过程,介绍静态变量、静态块的执行顺序。

  静态块的语法形式如下。

  1. static
  2. {
  3. 语句块
  4. }

  Java类首次装入JVM时,会对静态变量(含静态块)或方法进行一次初始化,方法不被调用是不会执行的,就是说静态变量和静态块是在类首次装载进JVM时被执行的。

  运行如下的程序,运行结果如图7.13所示。

  1. public class Student
  2. {
  3. private static String staticName = "静态姓名"; //静态变量
  4. private String stuName = ""; //学生姓名——私有变量
  5. //使用静态初始化块初始化
  6. static
  7. {
  8. System.out.println("***使用静态初始化块初始化***");
  9. System.out.println("静态块里显示静态变量值:" + staticName);
  10. }
  11. //使用初始化块初始化
  12. {
  13. this.stuName = "雷静";
  14. System.out.println("***使用初始化块初始化***");
  15. System.out.println("普通块里显示实例变量值:" + stuName);
  16. System.out.println("普通块里显示静态变量值:" + staticName);
  17. }
  18. //构造方法,用户初始化对象的成员变量
  19. public Student(String name){
  20. this.stuName = name;
  21. System.out.println("***使用有参构造函数初始化***");
  22. System.out.println("构造方法里显示实例变量值:" + stuName);
  23. System.out.println("构造方法里显示静态变量值:" + staticName);
  24. }
  25. public static void main(String[] args)
  26. {
  27. Student stu = new Student("王云");
  28. }
  29. }
7.4 static关键字 - 图4
图7.13 使用静态块初始化变量

  通过上面的例子可以看出,静态变量和静态块都是在类实例化对象前被执行的。