java 中常用的关键字有:final、static、extends、super、abstract、interface、implements。下面讲述
static 这个关键字。 static 翻译成中文静态的,java 中主要用于内存管理。
用 static 修饰的成员变量、方法、代码块、内部类是类维度的,非对象维度的。
static 修饰成员变量
- 静态变量/类变量:被 static 修饰的成员变量
- 实例变量:没有 static 修饰的成员变量
静态变量/类变量的特点:
- 当且仅当在类初次加载时会被初始化,所有类对象共享,内存中值存储一份
- 不需要创建对象就能访问,直接使用类名访问
- static 成员变量的初始化顺序按照定义的顺序进行初始化
实例变量的特点:
- 每个类对象都单独存储一份,互不影响
- 需要创建对象才能访问
@Slf4j
public class Person {
int age;
static String national; // 静态变量
public Person(int age) {
this.age = age;
}
public void show(){
log.info("age:{},national:{}",age,national);
}
}
public static void main(String[] args){
Person person1 = new Person(11);
Person person2 = new Person(12);
Person.national = "中国"; // 类名访问静态变量
person1.show();
person2.show();
}
输出:
static 修饰方法
- 静态方法/类方法:被 static 修饰的方法
- 实例方法:没有 static 修饰的方法
静态方法/类方法的特点:
- 它通过类直接被调用,无需创建类的对象
- 静态方法可以访问类中所有的静态变量和静态方法,不能访问实例变量和实例方法
- 静态方法中不能使用 this 、super 等对象关键字
@Slf4j
public class Person {
int age;
static String national;
public Person(int age) {
this.age = age;
}
// 静态方法可以访问静态变量,不能访问非静态变量
public static void printNational() {
log.info("national:{}", national);
// log.info("age:{}",age);
}
public void printAge() {
log.info("age:{}", age);
}
// 静态方法可以访问静态方法,不能访问非静态方法
public static void show1() {
printNational();
// printAge();
}
public void show2() {
printAge();
}
public void show() {
show1();
show2();
}
}
public static void main(String[] args){
Person person1 = new Person(11);
Person.national = "中国";
Person.show1(); // 类名访问静态方法
person1.show2();
}
// 输出:national:中国
// age:11
静态变量,静态方法的好处:
- 节省内存:所有类对象共有的相同变量可以设置为静态变量,只需要开辟一份空间
- 增加交互性:所有类共享的数据可以设置为静态变量,方便共同操作
- 使用方便:不需要创建对象就能访问,直接使用类名访问
static 修饰代码块
用于类初始化时,为类的静态变量赋初始值,提升程序性能。
静态方代码块特点:
- 可以置于类中任意地方,可以有多个,但不可以存在方法体内
- 类似于静态方法,可以访问类中所有的静态变量和静态方法,不能访问实例变量和实例方法
@Slf4j
public class Person {
int age;
static String national;
public Person(int age) {
this.age = age;
}
// 静态方法可以访问静态变量,不能访问非静态变量
public static void printNational() {
log.info("national:{}", national);
// log.info("age:{}",age);
}
public void printAge() {
log.info("age:{}", age);
}
// 静态方法可以访问静态方法,不能访问非静态方法
public static void show1() {
printNational();
// printAge();
}
public void show2() {
printAge();
}
// 可以访问类中所有的静态变量和静态方法,不能访问实例变量和实例方法
static {
national = "中国";
// age = 18;
}
static {
printNational();
// printAge();
}
}
public static void main(String[] args){
Person person1 = new Person(11);
}
// 输出: national:中国
static 修饰内部类
- 静态内部类向正常类一样可以定义成员变量、方法
- 静态内部类可以访问外部类的静态变量、静态方法,不能访问实例变量、实例方法
- 使用内部类时无需创建外部类对象,可以直接通过外部类名操作静态内部类
@Slf4j
public class Person {
int age;
static String national;
public Person(int age) {
this.age = age;
}
// 静态方法可以访问静态变量,不能访问非静态变量
public static void printNational() {
log.info("national:{}", national);
// log.info("age:{}",age);
}
public void printAge() {
log.info("age:{}", age);
}
public static class PersonBuild {
public int money;
static public boolean alive;
public PersonBuild(int money) {
this.money = money;
}
public static void printAlive() {
log.info("alive:{}", alive);
}
public void printMoney() {
log.info("money:{}", money);
}
// 可以访问静态变量、静态方法,不能访问非静态变量,非静态方法
public static void show1() {
national = "中国";
// age = 20;
printNational();
// printAge();
}
}
public void show2() {
// 在外部类中使用静态内部类方法
PersonBuild.printAlive();
PersonBuild personBuild = new PersonBuild(10000);
personBuild.printMoney();
}
}
public static void main(String[] args){
Person person1 = new Person(11);
// 在外部类之外使用静态类
Person.PersonBuild.alive = true;
Person.PersonBuild.show1();
person1.show2();
person1.printAge();
}
// 输出
national:中国
alive:true
money:10000
age:11
静态内部类使用场景
- 当外部类需要使用内部类,而内部类无需外部类资源,并且内部类可以单独创建时,考虑采用静态内部类的设计,在知道如何初始化静态内部类。例如 Builder 设计模式。
- 容器 linkedList 的 Node 节点就是内部静态类。