static主要有以下五个作用:

  • 静态变量
  • 静态方法
  • 静态代码块
  • 静态内部类
  • 静态导包

下面一一介绍。

静态变量

static修饰变量,使其成为静态变量。我们通常将static修饰的变量成为类变量,这主要是相对于属于对象的普通变量来说的,静态变量可以直接通过类名.变量使用。当然静态变量也是可以通过对象获取的,但是阿里巴巴Java开发手册建议直接通过类名访问,减少解析与内存成本。

public class StaticClass {
    public static String staticStr;
}

public class Main {
    public static void main(String[] args) {
        String str = StaticClass.staticStr;
    }
}

静态变量与非静态变量区别:

  • 静态变量属于类,被此类的所有对象共享,在内存中只有一份副本,在类初次加载时初始化
  • 非静态变量属于对象,在创建对象时初始化,在内存中存在多份副本,各个对象之间互不影响

具体的类的初始化过程可以看此篇博文:类的初始化过程

静态方法

static修饰方法,使其成为静态方法。同样的,我们经常将静态方法叫做类方法,静态方法也可以通过类名.方法名来访问。静态方法也可以通过对象获取,但是依然不建议这么做,理由同上。

public class StaticClass {
    public static String getStaticStr(){
        return "static string";
    }
}

public class Main {
    public static void main(String[] args) {
        String str = StaticClass.getStaticStr();
    }
}

静态方法注意事项:

  • 静态方法不能访问非静态方法与非静态变量,但非静态方法可以访问静态方法与静态变量
  • 静态方法中不能使用this,因为静态方法属于类,不依附于任何对象

静态代码块

静态代码块主要用于累的初始化操作,静态代码块中同样不能访问非静态方法与非静态变量。

静态代码块的主要作用是提升程序性能

public class Student {
    private Integer age;
    public Student(Integer age){
        this.age = age;
    }

    public Boolean isBetween(){
        Integer startAge = new Integer(10);
        Integer endAge = new Integer(20);
        return this.age.compareTo(startAge) >= 0 && this.age.compareTo(endAge) <= 0;
    }
}

isBetween()的作用是判断Student的年龄是否处于10-20岁,可以看到,每次进行判断时,都会生成startAge与endAge两个对象,造成内存浪费。若代码用静态代码块,如下所示。startAge与endAge都只会被初始化一次。所以很多时候会将只初始化一次的操作放到静态代码块中执行。

public class Student {
    private Integer age;
    private static Integer startAge;
    private static Integer endAge;
    
    static {
        Integer startAge = new Integer(10);
        Integer endAge = new Integer(20);
    }

    public Student(Integer age){
        this.age = age;
    }

    public Boolean isBetween(){
        return this.age.compareTo(startAge) >= 0 && this.age.compareTo(endAge) <= 0;
    }
}

静态内部类

静态内部类属于内部类的一种。详细内容请看此篇博文,此处不再赘述。Java内部类

这里主要讨论下静态内部类的作用。

为什么要有内部类?

  1. 方便将存在一定逻辑关系的类组织在一起,同时又能对外部隐藏。
  2. 如果涉及一个类B只是为了给类A使用,那么就可以将类B设计为内部类,防止其与其他类发生依赖关系。

再说一下为什么要有静态内部类。

  1. 静态内部类英文名叫做"static nested calss",即静态嵌套类。嵌套可以理解为我只是借用你的外壳,静态内部类和你外部类不是强依赖关系,没有外部类对象一样可以创建静态内部类实例;而且我也不需要访问你外部类的非静态变量和非静态方法,那么就可以把此内部类设计为静态内部类。
  2. 那么不符合上述要求的内部类,就应该设计为普通内部类。我作为内部类需要你外部类的对象才可以创建,或者我需要访问外部类的所有静态非静态的成员与方法。

静态导包

静态导包就是java包的静态导入。

一般我们导入一个类时

import com.xxx.....ClassName;

静态导入的话,如下所示。

import static com.xxx.....ClassName.*; // 导入此类中的所有静态方法
import static com.xxx.....ClassName.staticMethod; // 将*替换为静态方法名,只导入此静态方法

静态导入后,就可以在这个直接用方法名调用静态方法,而不必使用类名.静态方法名的方法。

举个例子,静态导包前:

public class Main {
    public static void main(String[] args) {
        System.out.println(Integer.MAX_VALUE);
        System.out.println(Integer.MIN_VALUE);
    }
}

静态导包后:

import static java.lang.System.*;
import static java.lang.Integer.*;

public class Main {
    public static void main(String[] args) {
        out.println(MAX_VALUE);
        out.println(MIN_VALUE);
    }
}

静态导入需要注意几个点:

  • 是import static,注意不要搞错顺序
  • 当多个静态导入的类中有相同的静态成员或是静态方法时,会产生歧义;当然,正常导入的包也可能会有这个问题。

现在编译器都可以直接帮你导入所需要的的包,静态导入了解即可。