先引入一份代码:
public class A{
public A(){
System.out.println("构造方法中a=30");
a=30;
}
{
System.out.println("构造代码块1中a=40");
a=40;
}
int a=init();
{
System.out.println("构造代码块2中a=60");
a=60;
}
public int init(){
System.out.println("初始化中a=90");
return 90;
}
static{
System.out.println("静态代码块1中B=100");
B=100;
}
static int B=staticInit();
static{
System.out.println("静态代码块2中B=400");
B=400;
}
public static int staticInit(){
System.out.println("初始化中B=500");
return 500;
}
public static void main(String[] args){
A p=new A();
A q=new A();
}
}
输出结果为:
静态代码块1中B=100
初始化中B=500
静态代码块2中B=400
构造代码块1中a=40
初始化中a=90
构造代码块2中a=60
构造方法中a=30
构造代码块1中a=40
初始化中a=90
构造方法中a=30
根据以上的运行结果我们会不由自主的产生几个问题,例如:
1.什么是静态代码块?
所谓的代码块就是一段独立的代码空间,那什么是静态代码块呢?说白了,静态代码块就是用static修饰的代码块。
2.它们的执行顺序是什么?
执行顺序:(优先级从高到低)静态代码块>mian方法>构造代码块>构造方法。
3.为什么在显示结果中静态代码块的内容只显示了一次?
在类加载的init阶段,类的类构造器中会收集所有的static块和字段并执行,static块只执行一次,由JVM保证其只执行一次。或者可以这样认为:static代码块只在类加载时执行,类是用类加载器来读取的,类加载器是带有一个缓存区的,它会把读取到的类缓存起来,所以在一次虚拟机运行期间,一个类只会被加载一次,这样的话静态代码块只会运行一次。
4.静态代码块的显著特点是什么?
随着类的加载而执行,而且只执行一次
5.static{ }(静态代码块)与{ }(非静态代码块)的异同点
相同点:都是在JVM加载类时且在构造方法执行之前执行,在类中都可以定义多个。
不同点:静态代码块在非静态代码块之前执行(静态代码块—>非静态代码块—>构造方法)。
静态代码块只在第一次new执行一次,之后不再执行,而非静态代码块在每new
一次就执行一次。
总结:静态代码块,在虚拟机加载类的时候就会加载执行,而且只执行一次;
非静态代码块,在创建对象的时候(即new一个对象的时候)执行,每次创建对象都会执行一次
6.静态代码块和静态方法的区别?
1)静态代码块是自动执行的; 静态方法是被调用的时候才执行的。
2)静态代码块可用来初始化一些项目最常用的变量或对象;静态方法可用作不创建对象也可能需要执行的代码。
7.关于静态代码块的认识?
1)静态代码块只能定义在类里面,它独立于任何方法,不能定义在方法里面。
2)静态代码块里面的变量都是局部变量,只在本块内有效。
3)静态代码块会在类被加载时自动执行,而无论加载者是JVM还是其他的类。
4)一个类中允许定义多个静态代码块,执行的顺序根据定义的顺序进行。
5)静态代码块只能访问类的静态成员,而不允许访问实例成员。实例方法可以访问静态和实例成员。
8.不允许静态方法访问实例成员变量的原因?
因为实例成员变量是属于某个对象的,而静态方法在执行时,并不一定存在对象。
同样,因为实例方法可以访问实例成员变量,如果允许静态方法调用实例方法,将间接地允许它使用实例成员变量,所以静态方法也不能调用实例方法。基于同样的道理,静态方法中也不能使用关键字this。
- 静态代码优先于非静态的代码的原因?
静态代码优先于非静态的代码,是因为被static修饰的成员都是类成员,会随着JVM加载类的时候加载而执行,而没有被static修饰的成员也被称为实例成员,需要创建对象才会随之加载到堆内存。所以静态的会优先非静态的。
总结:
静态代码块会随着类的加载而执行,而且只执行一次。当所有的静态代码块都执行结束后会执行main函数中的输出语句,然后会去执行非静态代码块,接着是执行构造方法。