7.4 static关键字

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

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

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

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

7.4.1 static关键字的使用

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

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

public class TestStatic

{

    public static void main(String[] args) 

    {

        Student wangYun = new Student();

        wangYun.avgAge = 22;                           //将Student类变量的值设置为22        

        System.out.println("王云所在班平均年龄为:" + wangYun.avgAge);

        Student liuJT = new Student();

        liuJT.avgAge = 21;                                  //将Student类变量的值设置为21        

        System.out.println("王云所在班平均年龄为:" + wangYun.avgAge);

        System.out.println("刘静涛所在班平均年龄为:" + liuJT.avgAge);

    }

}

class Student 

{ 

    public static int avgAge;                                   //类变量,存放平均年龄

}
copy

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

图7.10 类变量使用

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

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

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

public class TestStatic2

{

    public static void main(String[] args) 

    {

        Student.showAvgAge();       //调用静态方法           

        System.out.println("静态变量输出所在班平均年龄为:" + Student.avgAge);

    }

}

class Student 

{

    public static int avgAge = 22;                  //类变量,存放平均年龄

    public static void showAvgAge()  //静态方法输出班平均年龄

    {

        System.out.println("静态方法输出所在班平均年龄为:22");

    }

}
copy

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

图7.11 静态方法使用

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

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

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

public class Student 

{

    public int avgAge = 22;                           //实例变量,存放平均年龄

    public static void showAvgAge()  //静态方法调用实例变量——编译出错

    {

        System.out.println("静态方法输出所在班平均年龄为:" + avgAge);

    }

}
copy

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

图7.12 静态方法调用实例变量

7.4.2 Java静态块

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

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

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

  (3)初始化块初始化。

  (4)构造方法初始化。

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

  静态块的语法形式如下。

static

{

    语句块

}
copy

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

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

public class Student 

{

    private static String staticName = "静态姓名";       //静态变量

    private String stuName = "";                                    //学生姓名——私有变量

    //使用静态初始化块初始化

    static

    {       

        System.out.println("***使用静态初始化块初始化***");

        System.out.println("静态块里显示静态变量值:" + staticName);

    }

    //使用初始化块初始化

    {       

        this.stuName = "雷静";

        System.out.println("***使用初始化块初始化***");

        System.out.println("普通块里显示实例变量值:" + stuName);

        System.out.println("普通块里显示静态变量值:" + staticName);

    }

    //构造方法,用户初始化对象的成员变量

    public Student(String name){         

        this.stuName = name;

        System.out.println("***使用有参构造函数初始化***");

        System.out.println("构造方法里显示实例变量值:" + stuName);

        System.out.println("构造方法里显示静态变量值:" + staticName);

    }

    public static void main(String[] args) 

    {

        Student stu = new Student("王云");

    }

}
copy
图7.13 使用静态块初始化变量

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