也就是一个类中有很多部分的代码,它们的执行顺序是怎样的?
1、 静态代码块 和 main 方法:先执行 静态代码块,与位置无关。
2、 假如类中定义 静态成员变量(该变量是个对象,普通的成员变量也适用),那么会先创建对象:
**假如 2 的代码块在 1 的前面写,则先执行 2,是由位置决定的。而 main 始终在 1,2 最后,跟位置没有关系。 **
3、 需注意:
① 如果是非静态代码块、非静态成员变量(该变量是个对象),是不会执行的:
② 这个时候,只有在创建 Test 对象的时候(也就是它们所在类的对象),才会执行 非静态代码块、非静态成员变量(该变量是个对象):此时 三者的执行的顺序 是按照位置的先后。
4、 如果同时存在 非静态代码块、静态代码块、非静态成员变量(对象)、静态成员变量(对象):
先执行静态的东西,并且只执行一次;再执行非静态的东西(能执行的前提:先创建对象),创建多少个就执行多少次。
有资源类 Res、父类 Parent、子类 Children,测试类 Test。代码分别如下,那执行顺序是怎样的?
public class Res {
public Res(String str){
System.out.println(str + "方式:调用 Res 的构造方法,创建 Res 资源。");
}
}
public class Parent {
static Res parentRes = new Res("父类的静态成员变量,该变量(是父类创建 Res 对象)");
static {
System.out.println("父类的静态代码块");
}
{
System.out.println("父类的非静态代码块");
}
Res parentRes1 = new Res("父类的非静态成员变量,该变量(是父类创建 Res 对象)");
Res parentRes2;
public Parent(){
System.out.println("父类的无参构造");
parentRes2 = new Res("在父类的无参构造中创建 Res 对象");
}
public void sayHello(){
System.out.println("父类的普通方法");
}
}
public class Children extends Parent{
static Res childrenRes = new Res("子类的静态成员变量,该变量(是子类创建 Res 对象)");
static {
System.out.println("子类的静态代码块");
}
{
System.out.println("子类的非静态代码块");
}
Res childrenRes1 = new Res("父类的非静态成员变量,该变量(是子类创建 Res 对象)");
Res childrenRes2;
public Children(){
System.out.println("子类的无参构造");
childrenRes2 = new Res("在子类的无参构造中创建 Res 对象");
}
public void sayHello(){
System.out.println("子类的普通方法");
}
}
public class Test {
public static void main(String[] args) {
Children children = new Children();
children.sayHello();
System.out.println("*******");
//子类强转父类后,再调方法
((Parent) children).sayHello();
}
}
运行结果:
分析:
① 首先代码从 main 方法入口开始
② Children children = new Children();
创建子类对象、会调子类的构造器,子类构造器的首行默认会有 super() 方法,所以会 优先调父类的无参构造,所以会先加载 Parent 类,其中 静态代码块 和 静态成员变量 会优先执行,即输出前 2 行:
③ Parent 类加载完后,再去加载 Children 类,因为 先加载类再执行,所以输出第3、4行:
④ 类都加载完后,就开始创建对象,默认会先创建父类对象,但调构造器之前会先执行类中的 非静态东西,然后再开始通过父类自己的无参构造创建父类对象,所以输出第5、6、7、8行:
⑤ 父类的东西都搞完后,再开始搞子类的东西,同理,输出9、10、11、12行:
⑥ 创建对象完后,对象开始执行方法:children.sayHello();
,输出13、14行:
⑦ 虽然进行了强制类型转换,但对象还是来自内存中的子类对象。