代码块的基本介绍
代码块又称为初始化块,属于类中的成员(也就是类中的一部分),类似于一个方法,将逻辑语句封装在一个方法体中,用{ }包围起来。
但代码块和方法不同,它没有参数,没有返回值,有没有方法名,只有方法体,而且它不通过对象或类进行显示调用,而是在类被加载时,或调用对象时进行隐式调用。
它的基本语法结构如下:
[修饰符]{
代码
};
注意:
- 修饰符只有不写或static两种;
- 没有修饰符的叫普通代码块,被static修饰的叫静态代码块;
- 代码中的逻辑语句可以是Java中所有的逻辑语句(输入、输出、方法调用、循环、判断等);
- ;号可以写,也可以省略,看个人的编程习惯;
代码块的好处
(1).相当于另外一种形式的构造器(对构造器的一种补充机制),可以做初始化的操作;
(2).如果多个构造器中有重复的语句,可以抽取出来放到代码块中,以此提高代码的复用性;
代码演示:
public class Code01 {
public static void main(String[] args) {
Movie movie = new Movie("满江红");
System.out.println("-------------------");
Movie movie1 = new Movie("流浪地球2", 58);
}
}
class Movie {
private String name;
private int price;
{
System.out.println("电影屏幕打开....");
System.out.println("开始播放广告....");
System.out.println("正片开始");
}
public Movie(String name) {
System.out.println("Movie(String name)被调用");
this.name = name;
}
public Movie(String name, int price) {
System.out.println("Movie(String name, int price)被调用");
this.name = name;
this.price = price;
}
}
结果为
使用代码块的注意事项以及它的优先级
1.static代码块,它随着类的加载而执行,并且只执行一次。如果是普通代码块,每创建一个对象就执行一次。
2.类什么时候被加载
- 创建对象实例时(new对象);
- 创建子类对象实例,父类也会被加载;
- 使用类的静态成员时(静态属性、静态方法);
3.创建一个对象时,在一个类中的调用顺序
- 调用静态代码块和静态属性初始化(两者优先级一样,如有多个,按定义的顺序调用即可);
- 调用普通代码块和普通属性初始化(同上);
- 调用构造方法
演示代码:
public class Code02 {
public static void main(String[] args) {
A a = new A();
}
}
class A {
//普通属性初始化
private int a2 = getA2();
//静态属性初始化
public static int a1= getA1();
//静态代码块
static {
System.out.println("A的静态代码块被执行!");
}
{
System.out.println("A的普通代码块被执行!");
}
public static int getA1() {
System.out.println("getA1被调用");
return 100;
}
public int getA2() {
System.out.println("getA2被调用");
return 200;
}
public A() {
System.out.println("A的无参构造器被调用");
}
}
结果为:
4.当有继承关系时,他们的静态代码块,静态属性初始化,普通代码块,普通属性初始化,构造方法的调用顺序如下:
- 父类的静态代码块和静态属性;
- 子类的静态代码块和静态属性;
- 父类的普通代码块和普通属性;
- 父类的构造器;
- 子类的普通代码块和普通属性;
- 子类的构造器;
代码演示:
public class Code03 {
public static void main(String[] args) {
BB bb = new BB();
}
}
class AA {
private static int n1 = getN1();
static {
System.out.println("AA的静态代码块(父类)"); //2
}
{
System.out.println("AA的普通代码块(父类)"); //5
}
public int n2 = getN2();
public static int getN1() {
System.out.println("getN1(静态属性初始化--父类)"); //1
return 10;
}
public int getN2() {
System.out.println("getN1(普通属性初始化--父类)"); //6
return 20;
}
public AA() {
System.out.println("AA的构造器(父类)"); //7
}
}
class BB extends AA{
private static int n3 = getN3();
static {
System.out.println("BB的静态代码块(子类)"); //4
}
{
System.out.println("BB的普通代码块(子类)"); //8
}
public int n4 = getN4();
public static int getN3() {
System.out.println("getN3(静态属性初始化--子类)"); //3
return 30;
}
public int getN4() {
System.out.println("getN4(普通属性初始化--子类)"); //9
return 40;
}
public BB() {
System.out.println("BB的构造器(子类)"); //10
}
}
结果如下:
5.静态代码块只能调用静态成员(静态属性、静态方法),普通代码块可以调用任意成员
小结
- 静态代码块:在类加载JVM时初始化,且只被执行一次;常用来执行类属性的初始化;静态块优先于各种代码块以及构造函数;此外静态代码块不能访问普通变量。
- 构造代码块:每次调用构造方法,构造代码块都执行一次;构造代码块优先于构造函数执行;同时构造代码块的运行依赖于构造函数。
代码块的初始化:普通代码块在实例对象创建时进行初始化;静态代码块在类加载时进行初始化。
继承中代码块执行顺序:父类静态块 ==> 子类静态块 ==> 父类代码块 ==> 父类构造器 ==> 子类代码块 ==> 子类构造器 。