今天遇到了一些问题, 刚开始很混乱。后来一个一个的查,一个一个问题的去解决,现在豁然开朗了。记录一下:
起因是因为看一个帖子看到这样一段代码:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
public
class
Test {
Person person =
new
Person(
"Test"
);
static
{
System.out.println(
"test static"
);
}
public
Test() {
System.out.println(
"test constructor"
);
}
public
static
void
main(String[] args) {
new
MyClass();
}
}
class
Person{
static
{
System.out.println(
"person static"
);
}
public
Person(String str) {
System.out.println(
"person "
+str);
}
}
class
MyClass
extends
Test {
Person person =
new
Person(
"MyClass"
);
static
{
System.out.println(
"myclass static"
);
}
public
MyClass() {
System.out.println(
"myclass constructor"
);
}
}
输出结果为:
test staticmyclass static
person static
person Test
test constructor
person MyClass
myclass constructor
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
一开始看到结果的时候想不通为什么是这样子的,跟我想的一点都不一样啊。 费了半天劲儿都看不出来这样的结果,觉得自己真的是太欠缺了,懂的太少了。后来静下心研究了一下,慢慢来,不要急躁,会学到很多东西。
首先,我将自己的疑问列出来:
1.静态方法的初始化
2. new 一个子类的时候,父类构造是如何被调用的;
3.main方法与成员变量及方法的执行顺序。
首先解决第一个问题,静态方法的初始化,静态方法是被static修饰的方法,一般静态方法会在类被加载的时候就进行初始化, 而且只初始化这一次。所以你看到的输出结果,static是在最前面的。
第二个问题,new一个子类的时候,有static变量跟方法会先初始化。然后会先去加载父类的成员变量,方法, 与构造函数,如果父类中存在static方法或者变量,则先初始化static变量与方法,但是记住,static方法与变量只能被初始化一次,如果前面初始化过就不会再初始化第二次了。接下来就是初始化成员变量,然后调用构造函数。
第三个问题,程序开始运行时,系统会找到main方法所在的class,然后把main方法加载到内存中,从mian 函数的第一条开始执行,知道main的最后一条语句结束。但是class中存在static变量或者方法,也会进行初始化。所以这里输出的第一条是test static。 至于main所在的类中其他的成员变量喝构造函数只会在new 这个类时进行初始化,方法要在调用的时候才加载。
好了,现在我们来捋一捋。接下来在new MyClass
()的时候,先执行static方法,输出myclass static。因为MyClass
继承自Test,所以会先出初始化Test,而Test类在系统执行main之前就被加载了,也就是说Test类中的static方法已经被初始化过了,在这里就不会再进行二次初始化。接下来就初始化成员变量person,person是通过new Person()被初始化的,new Person() 会按照同样的顺序对Person类中的静态方法,成员变量,构造函数进行初始化。 所以,首先输出静态方法中的person static,然后调用构造函数,输出person Test。 person初始化完成之后就执行Test类的构造函数,输出test constructor。 然后在返回子类进行初始化,初始化成员变量 person (static已经被初始化过,不会再次进行初始化),同样到person类中执行构造函数(static已经被初始化过,不会再次进行初始化),输出person MyClass,然后执行myClass的构造函数,输出myclass constructor。
现在,清晰很多了吧。 所以 静态方法与main的执行关系是,静态方法与属性> main 方法, 子类初始化会先加载父类的变量跟方法,注意这里只是加载并不会创建一个父类对象。