写在开头
相信各位在写Java代码的时候一定对继承部分一定会有相应的疑惑,为什么这么写程序
就这么跑了呢,为什么那么些程序就又不太一样呢?且听我仔细剖析类的初始化顺序,我将
其中的道理娓娓道来
在一个类中
先做一个假设:
假设先进行静态成员初始化,再进行普通成员初始化
那么根据假设将实验过程分为三个步骤
1研究静态成员顺序问题
2研究普通成员顺序问题
3两者混合的顺序问题
1静态成员顺序问题
class Person{
private static String name = say();
static{
System.out.println("我是A的静态代码块");
}
public static String say(){
System.out.println("我是因为静态成员name初始化而被调用");
return "";
}
}
class Person{
static{
System.out.println("我是A的静态代码块");
}
private static String name = say();
public static String say(){
System.out.println("我是因为静态成员name初始化而被调用");
return "";
}
}
上面两段代码执行的结果分别是


那么得到第一个结论: 静态成员之间的初始化是同级的
2普通成员顺序问题
实际上普通成员在代码形式上少了static,这里就放一段代码以作演示,也不放结果了
class Person{
{
System.out.println("我是A的普通代码块");
}
private String name = say();
public String say(){
System.out.println("我是因为普通成员name初始化而被调用");
return "";
}
}
得到第二个结论:普通成员之间的初始化是同级的
PS:如果各位不信的话可以自己跑跑看
3两者混合的顺序问题
以下是证明过程:
class Person {
{
System.out.println("我是A的普通代码块");
}
private String name = say();
static {
System.out.println("我是A的普通代码块");
}
private static Integer age = year();
public String say() {
System.out.println("我是因为普通成员name初始化而被调用");
return "";
}
public static int year() {
System.out.println("我是因为静态成员name初始化而被调用");
return 0;
}
}
为了凸显静态成员初始化的优先性,本人还特意将静态代码块和属性放在普通成员后面

得到第三个结论:成员之间的初始化是同级的,并且静态成员初始化优先级高于普通成员
4加入构造器(构造方法)
那么问题来了:如果加上构造器会怎么样呢?
猜测:构造器在成员初始化完之后再初始化
以下是证明过程
class Person {
public Person(String name) {
System.out.println("我是Person的有参构造器");
this.name = name;
}
{
System.out.println("我是A的普通代码块");
}
private String name = say();
static {
System.out.println("我是A的静态代码块");
}
private static Integer age = year();
public String say() {
System.out.println("我是因为普通成员name初始化而被调用");
return "";
}
public static int year() {
System.out.println("我是因为静态成员name初始化而被调用");
return 0;
}
}
为了凸显成员初始化的优先性,特意将有参构造器放在最前面

于是得到了一个更加完善的初始化顺序结论:
在同一个类中,静态代码块和静态属性的初始化顺序是按照代码先后顺序执行的,并且是在
创建对象的时候最先进行的,然后是普通代码块和普通成员,这两者的执行顺序机制和静态
成员一样,最后是构造器的初始化。
并且本人还得到了一个意外发现:在创建对象的过程中是对一个作用域内的代码进行执行的。
比如我在代码块内添加代码块


系统并不会固执的找到所有的静态成员排到普通成员前进行初始化,而是锁定在一定范围内
进行的,这和后面的结论有所出入
好,那么问题又来了,如果我有一个父类呢?
当有继承关系时
先做一个假设:父类所有成员初始化完成再进行子类的初始化
还是分为三步:
1.普通成员
2.静态成员
3.混合成员
1普通成员
class Animal{
public Animal(String name) {
System.out.println("我是Animal的有参构造器");
this.name = name;
}
{
System.out.println("我是Animal的普通代码块");
}
private String name = say();
// static {
// {
// System.out.println("我是Animal的静态代码块的普通代码块");
// }
// System.out.println("我是Animal的静态代码块");
// }
// private static Integer age = year();
public String say() {
System.out.println("我是Animal的say()方法");
return "";
}
// public static int year() {
// System.out.println("我是因为静态成员name初始化而被调用");
// return 0;
// }
}
class Person extends Animal{
public Person(String name) {
super(name);
System.out.println("我是Person的有参构造器");
this.name = name;
}
{
System.out.println("我是Person的普通代码块");
}
private String name = say();
// static {
// {
// System.out.println("我是A的静态代码块的普通代码块");
// }
// System.out.println("我是A的静态代码块");
// }
// private static Integer age = year();
public String say() {
System.out.println("我是Person的say()方法");
return "";
}
// public static int year() {
// System.out.println("我是因为静态成员name初始化而被调用");
// return 0;
// }
}


这里发现了一个奇怪的现象:似乎父类的普通成员初始化在子类之后。但是想想感觉哪里有
问题。于是乎当本人在仔细看时,发现了这里面子类重写了父类的方法,那么根据动态绑定
机制,此时的运行类型时子类类型那么会找到子类中和父类相同名字的方法进行调用;将其
中的重写方法进行修改;得到如下结果。

似乎与假设相应证明。
2静态成员
那么如果加上静态成员呢?
一下是证明过程
class Animal {
public Animal(String name) {
System.out.println("我是Animal的有参构造器");
this.name = name;
}
static {
System.out.println("我是Animal的静态代码块");
}
private static Integer age = year();
{
System.out.println("我是Animal的普通代码块");
}
private String name = noise();
public String noise() {
System.out.println("我是Animal的普通成员name");
return "";
}
public static int year() {
System.out.println("我是Animal的静态成员year");
return 0;
}
}
class Person extends Animal {
public Person(String name) {
super(name);
System.out.println("我是Person的有参构造器");
this.name = name;
}
{
System.out.println("我是Person的普通代码块");
}
private String name = say();
static {
System.out.println("我是Person的静态代码块");
}
private static Integer age = year();
public String say() {
System.out.println("我是Person的普通成员name");
return "";
}
public static int year() {
System.out.println("我是Person的静态成员age");
return 0;
}
}
其中包含了所有的成员(除了内部类),别问为什么没有内部类因为本人自己还没搞清楚
结果如下:

可见之前的假设被推翻。
结果呈现静态成员初始化一定高于普通成员,并且父类成员初始化一定先于子类成员;并且前者优先级高于后者
那么下一个最终结论:
在同一个类中的执行顺序是:
静态成员-->普通成员-->构造器
在不同类中(这里暂时限定在一个父类和一个子类且不涉及动态绑定和其他机制时):
静态父类成员-->静态子类成员-->父类其他成员-->子类其他成员
5436

被折叠的 条评论
为什么被折叠?



