Java 代码块和类的执行调用顺序
1 什么是代码块
代码块称之为初始化块,属于类中的一部分成员。类似于类中的方法,但和方法不同的是代码块没有方法名,没有返回,没有参数,只有用大括号{}括起来的方法体。
2 如何用
[修饰符]{
代码......
};
特别声明:
(1)修饰符可有可无,如果添加的话,只能添加static。
(2)使用static修饰的叫静态代码块,没有static修饰的叫普通代码块。
(3)块内可写任何逻辑语句,例如输入、输出、方法调用、循环、判断等。
(4)大括号末尾的 ;可写可不写。
(5)代码块在对象穿件时便会执行,且执行顺序先与构造器。
3 为何有代码块的出现
参考网上的说法:
(1)相当于另外一种形式的构造器,是对构造器的补充机制,可以做一系列的程序初始化操作。
(2)如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的重用性。
我们创建两个类 Dog类,Dog类有两个构造方法,每个构造方法都要求执行输出“我饿了,要吃饭...”的操作,下面我们用代码块的形式实现一下。
//Dog类
class Dog{
private String name;
private int age;
public Dog(){
System.out.println("Dog的空构造方法");
}
public Dog(String name,int age){
System.out.println("Dog的全构造方法");
}
{
System.out.println("Dog的普通代码块,我饿了,要吃饭...");
}
}
//main方法
public static void main(String[] args) {
Dog dog=new Dog();
Dog dog1=new Dog("大黄",1);
}
运行结果如下:
从结果我们可以看出,虽然代码块在程序中是写在最后面的,但是创建对象执行时是最先执行的。代码块调用的顺序优先于构造器....
4 一个类什么时候会加载?
在继续讲解下面的知识点前,先提示一个非常重要的知识点,即一个类在什么时候会加载,主要有3种情况,如下:
(1)当创建对象实例时(new)。
(2)创建子类对象实例时,父类也会被加载。
(3)使用类的静态属性和静态方法时。
代码演示:
(1)创建对象实例,也就是new一个对象,这个都知道,不再进行演示。
(2)创建子类对象实例,父类也会被加载。
class Father{
public Father(){
System.out.println("我是Father类的空构造...");
}
}
class Son extends Father{
public Son(){
System.out.println("我是Son类的空构造...");
}
}
//main方法中创建 Son对象
Son son=new Son();
看输出结果:
(3)使用静态属性和静态方法时,类会加载。
class A{
public static String name="wqq";
static {
System.out.println("A类的代码块");
}
public static void method01(){
System.out.println("A类的静态方法");
}
}
//main方法
public static void main(String[] args) {
System.out.println(A.name);
}
输出结果:
注意:此时A类已经被加载了,但是默认会执行静态的代码块,不会执行普通的代码块,我们将代码块的static去掉,在看结果如下:
class A{
public static String name="wqq";
{
System.out.println("A类的代码块");
}
}
5 代码块使用注意事项和细节
(1)static代码块即静态代码块,随着类的加载而执行,是对类进行初始化,且只会执行一次,当之后再创建对象时,静态代码块不会再执行。普通代码块每创建一次对象便会执行一次。
(2)普通代码块,在创建对象实例时,会被默认调用,每当创建一次,便会调用一次。如果只是使用类的静态成员时,普通代码块不会被调用执行。
6 创建对象类的调用顺序
当创建一个对象时,类默认加载的内容也是有顺序的,我们的印象往往是当new一个对象时,默认会首先加载其构造方法,现实是构造方法的加载顺序级别最低,具体的加载顺序如下:
(1) 静态代码块和静态属性的初始化。静态代码块和静态属性的初始化调用优先级一样,当两者碰在一起时,则按照代码的定义位置顺序执行。
(2)普通代码块和普通属性的初始化。普通代码块和普通属性的初始化的优先级一样,当两者碰在一起时,则按照代码的定义位置顺序执行。
(3)构造方法
实例演示:
首先我们先定义一个Cat实体类,里面包含了静态属性和静态代码块、普通属性和普通代码块、构造方法。
class Cat{
//普通属性的初始化
private String name=getCatName();
//静态属性的舒初始化
private static String color=getCatAge();
public Cat(){
System.out.println("构造方法==========");
}
{
//普通代码块
System.out.println("普通代码块......");
}
static {
//静态代码块
System.out.println("静态代码块......");
}
private String getCatName() {
System.out.println("对普通属性的初始化");
return "大白菜";
}
private static String getCatAge() {
System.out.println("对静态属性的初始化");
return "白色";
}
}
//在main方法中创建该对象
Cat cat = new Cat();
运行main()方法得到的结果如下:
7 含有继承关系时创建对象类的调用顺序
在实际的开发中往往有很多的继承关系,下面我们将介绍如果一个类继承了其他的类,如A extends B。当创建了A对象后,那么他们内部的默认加载顺序又是什么样呢?下面我我们直接说结论,对于过程的演示这里不再进行演示,感兴趣的话可以模仿上面的例子写一下。
加载顺序如下:
(1)父类的静态代码块和静态属性的初始化。
(2)子类的静态代码块和静态属性的初始化。
(3)父类的普通代码块和普通属性的初始化。
(4)父类的构造方法。
(5)子类的普通代码块和普通属性的初始化。
(6)子类的构造方法。
声明:静态代码块只能直接调用静态属性和静态方法;普通代码块可以调用任意成员。