可能学过java的人都应该知道类的继承,子类总是先执行父类的构造方法,然后再执行本类的构造方法来实例化对象,下面我们先来看一个例子来体现这一规则:
class Test
{
public static void main(String[] args)
{
B b = new B();
}
}
// 父类
class A
{
public A()
{
System.out.println("父类的构造函数...");
}
}
// 子类
class B extends A
{
public B()
{
System.out.println("本类的构造函数...");
}
}
大家一定会想,这么简单的一个程序算什么呢,大家应该都能分析出来答案了
父类的构造函数...
本类的构造函数...
这就反映了先父类的构造->本类的构造的执行顺序;
那现在大家再用这个思路来分析这个看似简单,实际暗藏了些许陷阱的几十行代码:
class Test
{
public static void main(String[] args)
{
A a = new B();
}
}
class A
{
int age = 11;
{
System.out.print(age + " ");
age = 22;
System.out.print(1 + " ");
}
public A()
{
System.out.print(2 + " ");
printAge();
}
public void printAge()
{
System.out.print(this.age + " ");
}
}
class B extends A
{
int age = 3;// {}初始化块
{
System.out.print(3 + " ");
}
public B()
{
System.out.print(4 + " ");
printAge();
}
public void printAge()
{
System.out.print(this.age + " ");
}
}
大家先来分析一下上面这个代码会输出什么?
首先我们先来看看正确的输出结果,再来分析其缘由;正确的结果如下:
11 1 2 0 3 4 3
怎么样,大家分析结果正确了吗?或者是否会对这个结果有怀疑呢,不用怀疑,将这个程序段复制运行一下你将会看到这个可爱的结果了;
那为什么结果是这样呢?现在我就带大家一起来分析一下这段代码,分析完之后你将会对 对象实例化顺序有一个新的认识;
分析之前我先大家说一下对象实例化的几个基本顺序:
- 给父类和子类的成员变量分配内存空间,并初始化值(这里涉及基本数据类型的默认值的知识,在这里就不细说了);
- 执行父类的成员变量声明和初始化块(顺序执行)
- 执行父类的构造函数(具体执行哪个构造函数是由子类的构造函数决定的)
- 执行子类的成员变量声明和初始化块(也是顺序执行)
- 最后才是子类的构造函数的执行
好了,现在我们顺着这个步骤来分析一下这段代码,你清楚答案为什么是这个了:
给父类 A 和子类 B 的 age 成员分配内存空间,由于 age 是 int 类型,所以默认值都是 0 ,内存变化图如下:
执行父类的成员变量声明和初始化块(顺序执行)
int age = 11;// 内存空间中父类的age值变为 22 { System.out.print(age + " "); // 这时输出 11 age = 22; // 内存空间中父类的age值变为 22 System.out.print(1 + " ");// 输出 1 }
执行完上面的语句之后内存最后的情况如下:
子类的age依然是 0
这时输出的值是:
11 1执行父类 A 的构造函数(具体执行哪个构造函数是由子类的构造函数决定的)
public A() { System.out.print(2 + " ");// 会输出 2 printAge();// 因为这个函数在子类中被重写了,所以实际执行的是子类的那个方法,输出的是子类的 age 值,而此时子类 age 的值从刚才的内存中可以看出是:0 }
这时输出的值是:
11 1 2 0执行子类 B 的成员变量声明和初始化块(也是顺序执行)
int age = 3;// 子类的 age 变为 3 { System.out.print(3 + " "); // 输出 3 }
内存变化如下:
这时输出的值是:
11 1 2 0 3执行子类 B 的构造函数
public B() { System.out.print(4 + " "); // 输出 4 printAge(); // 调用子类的方法,输出子类 B 的 age 值,这是 age 的值是 3,所以输出 3 }
所以最后的结果是:
11 1 2 0 3 4 3
好了,现在时间点是 22:22,是时候洗澡去了,今天的培训笔记就先总结到这里吧!
不知道大家看完我总结的这篇笔记如何,我自己在听这个知识点的时候也是一脸的迷茫,怎么会这样的结果呢,最后一听内存变化的分析结果之后,就一切都明了啦;
所以看来自己还是不是很清楚对象的时候化顺序的,希望这个分析对大家有所收获。
总结的不好或者不对的地方,还请各位指出,学习是一个交流互动的过程,每个人看到的角度有时候确实挺大的,所以有时候会发现不一样的东西。
更多的JAVA学习总结,求关注我的每日笔记总结。bye!