总结(子类对象的实例化过程)(创建子类对象)
1、类加载:先类加载父类,再类加载子类。
1 base 静态代码块 (父类中的)
打印 base 静态代码块
2 sub 静态代码块 (子类中的)
打印 sub 静态代码块
2、调用构造方法(类加载完毕后)
1 找到子类的无参构造方法
2 //super(); 这里隐含了super() 先去找父类无参构造
3 //super(); 找到父类的无参构造方法 这里隐含了super() 但是Object的默认无参对程序没有影响
4 继续执行父类的无参构造:
打印 base 构造代码块 base无参构造
5 结束父类的构造方法执行后,开始执行子类成员变量的初始化,先执行构造代码块,最后执行子类自己的构造方法
打印 sub 构造代码块 sub 无参构造
最终的打印结果为:
base 静态代码块
sub 静态代码块
base 构造代码块
base无参构造
sub 构造代码块
sub 无参构造
代码(作业2)(试题)
public class Test1 {
public static void main(String[] args) {
//创建子类对象,要先类加载父类 再类加载子类 0
//父子类都类加载完毕后,开始调用构造方法 3
Sub sub = new Sub();
}
}
class Base{
//先类加载父类,于是静态代码块执行,这里最先输出 1
static {
System.out.println("base 静态代码块");
}
{
System.out.println("base 构造代码块");
}
public Base(){
//super(); 找到父类的无参构造方法 这里隐含了super() 但是Object的默认无参对程序没有影响 6
System.out.println("base无参构造"); //执行完Object类的默认无参后,继续执行父类的无参构造 打印 7
}
}
class Sub extends Base{
//再类加载子类,于是静态代码块执行,这里第二个输出 2
static {
System.out.println("sub 静态代码块");
}
//结束父类的构造方法执行后,开始执行子类成员变量的初始化,先执行构造代码块 8
{
System.out.println("sub 构造代码块");
}
//找到子类的无参构造方法 4
public Sub(){
//super(); 这里隐含了super() 先去找父类无参构造 5
System.out.println("sub 无参构造"); //最后执行子类自己的构造方法 9
}
}
有参构造的情况(一道面试题)
JVM运行时内存图分析
代码(作业3)
public class Obj3 extends Obj1 {
//这个和Obj1中一模一样,先去执行Obj2的无参构造 11
Obj2 ob2 = new Obj2();
public Obj3(){
//super() 找到自身类的无参构造方法,这里隐含了super()去找父类无参构造方法 3
//父类的构造方法执行完后,转而执行当前对象的成员变量初始化 10
System.out.println("obj3"); //执行完当前对象的初始化,这里是最后执行的 12
}
//看代码题目一定要先找main方法 0
public static void main(String[] args) {
//创建自身对象,自身类有父类,先类加载父类再加载子类自己 1
//类加载都结束后,开始创建对象,找自身类的无参构造方法 2
Obj3 obj3 = new Obj3();
}
}
class Obj1 {
//先进行当前类的成员变量初始化,再执行构造方法 6
//这里就是一个成员变量,不要被吓住了
//发现这里是创建了一个Obj2对象,于是去这个类中调用Obj2的无参构造
Obj2 ob2 = new Obj2();
public Obj1() {
//super(),隐含了super()但是这里是Object无参构造对程序没有影响 4
//执行完Object的默认无参后,转回来初始化当前类的成员变量 5
System.out.println("Obj1"); //执行完自身成员变量初始化后,执行构造方法 9
}
}
class Obj2 {
public Obj2() {
//这里也隐含了super()但是对程序没有影响 7
System.out.println("obj2"); //执行完Object类的无参构造后 执行该类构造方法 8
//这里再执行一次 12
}
}