static 关键字主要有以下五种应用场景:

  • 修饰成员变量
  • 修饰成员方法
  • 静态代码块
  • 修饰内部类(只能修饰内部类,也就是静态内部类)
  • 静态导包

下面我将对这五种应用场景进行一些注意事项的说明。

1、修饰成员变量

被 static 修饰的成员变量叫做静态变量,静态变量不属于某个对象,而是属于当前类。
静态变量有两种访问方式:

类名.静态变量

对象.静态变量(不推荐)

2、修饰成员方法

被 static 修饰的成员方法叫做静态方法,静态方法不属于某个对象,而是属于当前类。
静态方法有两种访问方式:

类名.静态方法

对象.静态方法(不推荐)

在静态方法中不能使用 this 和 super 两个关键字

3、静态代码块

代码块大致可以划分为三种:静态代码块、构造代码块、普通代码块,代码格式如下:

public class StaticTest {
    // 静态代码块
    static { }

    // 构造代码块
    { }

    public void hello() {
        // 普通代码块
        { }
    }
}

静态代码块有以下几点需要注意:

  1. 静态代码块只会在类加载时执行,且只会执行一次
  2. 静态代码块不能访问非静态变量和非静态方法
  3. 静态代码块不能定义在任何方法内,包括静态方法
  4. 在静态代码块中不能使用 this 和 super 两个关键字

静态代码块、构造代码块和构造器执行顺序如下:

静态代码块 --> 构造代码块 --> 构造器

在继承关系中三者执行顺序如下:

父类静态代码块 --> 子类静态代码块 --> 父类构造代码块 --> 父类构造器 --> 子类构造代码块 --> 子类构造器

注意:静态代码块只在类加载时执行一次,但构造代码块每创建一个实例对象都会执行一次。

如果想要了解更多执行顺序相关的知识可以参考:static 静态代码块以及各代码块之间的执行顺序。

4、修饰内部类

静态内部类与非静态内部类之间最大的区别是:非静态内部类在编译完成之后会隐含地保存着一个引用,该引用指向创建它的外围类;而静态内部类却没有,没有这个引用就意味着它的创建不需要依赖外围类的创建,并且它不能使用任何外围类的非 static 成员变量和方法

5、静态导包

静态导包格式为:import static 。这两个关键字连用可以指定导入某个类中的指定静态资源,并且不需要使用类名调用类中静态成员,可以直接使用类中静态成员变量和成员方法。

举个例子,没使用静态导包前代码如下:

public class Demo {
    public static void main(String[] args) {
        int max = Math.max(6, 9);
        System.out.println(max);
    }
}

使用静态导包后代码如下:

import static java.lang.Math.*;

public class Demo {
    public static void main(String[] args) {
        int max = max(6, 9);
        System.out.println(max);
    }
}

注意

静态只能访问静态,但非静态既能访问静态也能访问非静态。

示例代码如下:

public class Demo02 {
    private static int a;
    private int b;
    
    static {
        a = 1;
        // b = 2;会报错
        // methodB();会报错
        // 创建对象的话可以间接访问非静态资源
        new Demo02().b = 2;
        new Demo02().methodB();
    }
    
    {
        methodA();
        methodB();
        a = 1;
        b = 2;
    }

    public static void methodA() {
        a = 1;
        // b = 2;会报错
        // methodB();会报错
        // 创建对象的话可以间接访问非静态资源
        new Demo02().b = 2;
        new Demo02().methodB();
    }

    public void methodB() {
        a = 1;
        b = 2;
        methodA();
    }
}