关键字Static
static可以修饰成员变量 / 方法 / 代码块 / 内部类
-
Static修饰成员变量
-
静态成员变量
-
属于类
-
类名.变量名
-
被这个类所有的对象共享
-
静态成员变量只加载一次
-
不要在构造方法中初始化
-
-
普通成员变量
- 属于对象
- 对象名.变量名
- 一个对象一个变量
public class StaticVariate { int a; //在类加载的时候,会将静态内容也加载到方法区的静态域中 //静态的内容先于对象存在 //这个静态内容被所有该类的对象共享 static int b; public static void main(String[] args) { StaticVariate staticVariate1 = new StaticVariate(); staticVariate1.a = 1; staticVariate1.b = 5; StaticVariate staticVariate2 = new StaticVariate(); staticVariate2.a = 10; staticVariate2.b = 50; StaticVariate staticVariate3 = new StaticVariate(); staticVariate3.a = 100; staticVariate3.b = 500; System.out.println(staticVariate1.a); System.out.println(staticVariate2.a); System.out.println(staticVariate3.a); System.out.println(staticVariate1.b); System.out.println(staticVariate2.b); System.out.println(staticVariate3.b); //静态属性也称为类属性,非静态属性也被称为实例变量 //静态变量可以使用类名.属性名调用 System.out.println(StaticVariate.b);// 强制建议使用这种方式调用 } }
什么时候进行类加载
- 使用new关键词,即实例化对象
- 调用静态成员变量时,当使用静态成员变量时对象不一定存在
- 调用静态方法
-
-
Static修饰方法
public class StaticFunction { int a; static int b; public void a(){ System.out.println("-------a-------"); } public static void b(){ System.out.println("----------b--------"); System.out.println(b); //System.out.println(a);报错,因为静态方法先于对象存在因此无法找到这个对象的a,但是静态变量可以找到,因为静态变量也先于对象存在 //a();报错,因为非静态方法不先于对象存在,因此在这个静态方法存在时,a()方法并不存在 } public static void main(String[] args) { StaticFunction staticFunction = new StaticFunction(); //非静态方法通过对象名.方法调用 staticFunction.a(); //静态方法可以通过对象名.方法调用。也可以通过类名.方法调用 staticFunction.b(); StaticFunction.b();// 强制使用这个 } }
-
Static修饰代码块
public class StaticChunk { int a; static int b; public void a(){ System.out.println("----A------"); //普通代码快 //可以限制局部变量的作用范围 { System.out.println("普通代码块"); int num = 10; System.out.println(num); } } public static void b(){ System.out.println("======B======="); } //构造快 { System.out.println("这是构造快"); } //静态快 static { //静态快只能访问静态属性和静态方法 System.out.println("-----------这是静态快----------"); System.out.println(b); b(); } public StaticChunk(int a){ this.a = a; System.out.println("这是构造器------"); } public static void main(String[] args) { StaticChunk staticChunk1 = new StaticChunk(1); staticChunk1.a(); StaticChunk staticChunk2 = new StaticChunk(2); staticChunk2.a(); } }
运行结果
代码块执行顺序
首先,执行静态代码块只在类加载时执行一次(优先于main方法和构造方法),所以一般创建工厂,数据库的初始化信息放在静态代码块,一般用于执行一些全局化的初始化操作。(比如加载图片)
再执行构造代码块(不常用)
再执行构造器
再执行方法中的普通块
静态代码块 > 构造代码块 > 构造方法
有父子类关系的执行顺序
public class Father { public Father() { System.out.println("这是父类的构造方法"); } { System.out.println("这是父类的构造代码块"); } static { System.out.println("这是父类的静态代码块"); } public static void fatherStatic() { System.out.println("这是父类的静态方法"); } }
public class Children extends Father { public Children() { System.out.println("这是子类的构造方法"); } { System.out.println("这是子类的构造代码块"); } static { System.out.println("这是子类的静态代码块"); } public static void childrenStatic() { System.out.println("这是子类的静态方法"); } }
结果:
顺序:父类静态代码块 > 子类静态代码块 > 父类构造代码块 > 父类构造方法 > 子类构造代码块 > 子类构造方法
静态代码块和静态成员变量没有先后顺序,谁先写谁先执行,如果静态代码块在前,不能对静态成员变量进行运算
注意⚠️:静态代码块,静态方法只能调用静态的方法和静态的成员变量,非静态方法可以调用静态方法和成员变量