Java语言当中static关键字可以用来修饰变量、方法、代码块、内部类等。以下着重记录这四种用法。
1 静态变量
即使用static关键字修饰的变量,与之相对的是实例变量。
- 静态变量:也被称为类变量,顾名思义该变量是属于类的(而不是属于某个特定实例对象),不管该类存在多少个实例对象,静态变量在内存当中只保存了一份,被所有实例对象所共享。可以通过类名直接来访问它,需要注意的是不能通过某个实例对象的引用来访问。
- 实例变量:与静态变量不同的是,每实例化一个对象,就会创建一份实例变量,可以理解为它是与各个实例相关联的。
2 静态方法
即使用static关键字修饰的方法。与静态变量类似,静态方法不依赖于任何实例,其在类加载的时候就存在了,因此静态方法必须有实现。需要注意的是,静态方法中只能访问所属类的静态字段和静态方法,方法中不能使用this、super关键字,因为这两个关键字与某个特定实例相关联。
public class A {
private static int x; // Static field
private int y; // Non-static field
public static void func1(){ // Static method
int a = x;
// int b = y; // Non-static field 'y' cannot be referenced from a static context
// int b = this.y; // 'A.this' cannot be referenced from a static context
}
}
3 静态代码块
即使用static关键字修饰的代码片段:
public class A {
static {
System.out.println("static code segment");
}
public static void main(String[] args) {
A a1 = new A();
A a2 = new A();
}
}
类初始化时静态代码段只会执行一次,运行上面代码的输出结果如下:
static code segment
4 静态内部类
非静态内部类依赖于外部类的实例,换言之,首先需要创建外部类的实例,再通过外部类的实例去创建内部类的实例对象。而静态内部类则不需要,可直接被实例化。
public class OuterClass {
class InnerClass {
}
static class StaticInnerClass {
}
public static void main(String[] args) {
// InnerClass innerClass = new InnerClass(); // 'OuterClass.this' cannot be referenced from a static context
OuterClass outerClass = new OuterClass();
InnerClass innerClass = outerClass.new InnerClass();
StaticInnerClass staticInnerClass = new StaticInnerClass();
}
}
需要注意的是,静态内部类不能访问外部类的非静态的变量和方法。
5 初始化顺序
静态变量和静态语句块的执行优先于实例变量和普通语句块,至于静态变量和静态语句块的初始化顺序取决于它们在代码中的书写顺序,最后才是构造函数的初始化,因此我们可以得到如下的执行顺序(默认假设书写顺序为变量在前,语句块在后):
- 静态变量
- 静态语句块
- 实例变量
- 普通语句块
- 构造函数初
- 最后是则是普通方法调用
存在继承关系时情况稍复杂一些,执行顺序如下:
- 父类的静态变量、静态语句块
- 子类的静态变量、静态语句块
- 父类的实例变量、普通语句块
- 父类的构造函数
- 子类的实例变量、普通语句块
- 子类的构造函数
鉴于笔者还是入门小白,若有错误之处,还请各位批评指正,感谢!