实践探索JAVA初始化过程
程序员文章站
2024-01-03 21:21:16
...
1.JAVA在初始化的时候首先初始化静态代码块(只执行一次),然后非静态代码块,然后构造方法。
2.在各个代码块中顺序执行。
3.在存在继承关系的时候顺序为:父类static -> 子类static -> 父类非static -> 父类构造方法 -> 子类非static ->子类构造方法。
无继承,无层次:
public class A {
static {
System.out.println("a-static1");
System.out.println("a-static2");
}
{
System.out.println("a-not-static1");
System.out.println("a-not-static2");
}
public A() {
System.out.println("A构造方法1");
System.out.println("A构造方法2");
}
public static void main(String[] args) {
A a = new A();
}
}
}
执行结果:
a-static1
a-static2
a-not-static1
a-not-static2
A构造方法1
A构造方法2
与设想一样,静态非静态然后构造函数,各代码块顺序执行。
有继承,无层次:
public class A {
static {
System.out.println("a-static1");
System.out.println("a-static2");
}
{
System.out.println("a-not-static1");
System.out.println("a-not-static2");
}
public A() {
System.out.println("A无参构造方法1");
System.out.println("A无参构造方法2");
}
public A(B b) {
System.out.println("A有参构造方法1");
System.out.println("A有参构造方法2");
}
}
public class B extends A{
static {
System.out.println("B-static");
}
{
System.out.println("B-not-static");
}
public B() {
System.out.println("B-construct");
}
}
public class Test {
public static void main(String[] args) {
new B();
}
}
执行结果:
a-static1
a-static2
B-static
a-not-static1
a-not-static2
A无参构造方法1
A无参构造方法2
B-not-static
B-construct
无继承,有层次:
public class A {
static {
new B();
System.out.println("a-static1");
System.out.println("a-static2");
}
{
System.out.println("a-not-static1");
System.out.println("a-not-static2");
}
public A() {
System.out.println("A无参构造方法1");
System.out.println("A无参构造方法2");
}
public A(B b) {
System.out.println("A有参构造方法1");
System.out.println("A有参构造方法2");
}
}
public class B {
static {
System.out.println("B-static");
}
{
System.out.println("B-not-static");
}
public B() {
System.out.println("B-construct");
}
}
public class Test {
public static void main(String[] args) {
new A();
}
}
执行结果:
B-static
B-not-static
B-construct
a-static1
a-static2
a-not-static1
a-not-static2
A无参构造方法1
A无参构造方法2
按照规律先执行A的static块,初始化完B()才会去接着执行。
再来一个例子:
public class A {
static {
new A();
System.out.println("a-static1");
System.out.println("a-static2");
}
{
System.out.println("a-not-static1");
System.out.println("a-not-static2");
}
public A() {
System.out.println("A无参构造方法1");
System.out.println("A无参构造方法2");
}
public A(B b) {
System.out.println("A有参构造方法1");
System.out.println("A有参构造方法2");
}
}
public class Test {
public static void main(String[] args) {
new A();
}
}
结果:
a-not-static1
a-not-static2
A无参构造方法1
A无参构造方法2
a-static1
a-static2
a-not-static1
a-not-static2
A无参构造方法1
A无参构造方法2
先去执行A的static块,然后static块中有new A()的操作,所以去执行,但是static块已经被初始化了,所以不执行,执行非静态代码块和构造函数,执行完static块中的new A()操作了,然后接着执行。。。(省略)
如果我的层次放在构造函数中会怎么样?
public class A {
static {
System.out.println("a-static1");
System.out.println("a-static2");
}
{
System.out.println("a-not-static1");
System.out.println("a-not-static2");
}
public A() {
System.out.println("A无参构造方法1");
System.out.println("A无参构造方法2");
}
public A(B b) {
System.out.println("A有参构造方法1");
System.out.println("A有参构造方法2");
}
}
public class B {
static {
System.out.println("B-static");
}
{
System.out.println("B-not-static");
}
public B() {
System.out.println("B-construct");
}
}
public class Test {
public static void main(String[] args) {
new A(new B());
}
}
执行结果:
a-static1
a-static2
B-static
B-not-static
B-construct
a-not-static1
a-not-static2
A有参构造方法1
A有参构造方法2
这个结果看的我有点吃惊,他首先执行A的static块这是没有问题的,但是后边在执行非static块之前先去把B整个初始化的流程给执行完了,然后再执行下面步骤。由于本人水平有限,暂时无法解释到虚拟机底层的流程到底是怎么执行的。还希望大佬们不吝赐教。
有层次,有继承:
public class A {
static {
new B();
System.out.println("a-static1");
System.out.println("a-static2");
}
{
System.out.println("a-not-static1");
System.out.println("a-not-static2");
}
public A() {
System.out.println("A无参构造方法1");
System.out.println("A无参构造方法2");
}
public A(B b) {
System.out.println("A有参构造方法1");
System.out.println("A有参构造方法2");
}
}
public class B extends A{
static {
System.out.println("B-static");
}
{
System.out.println("B-not-static");
}
public B() {
System.out.println("B-construct");
}
}
public class Test {
public static void main(String[] args) {
new A();
}
}
执行结果:
B-static
a-not-static1
a-not-static2
A无参构造方法1
A无参构造方法2
B-not-static
B-construct
a-static1
a-static2
a-not-static1
a-not-static2
A无参构造方法1
A无参构造方法2
与我们的逻辑无误。首先A去初始化,在static块中遇到了new B(),B又是A的子类,那B先去初始父类A,但是A的static块已经被执行过了。然后执行子类static块,然后父类非静态代码块以及构造方法,然后子类非静态代码块以及构造方法,然后Astatic块中的new B()就执行完了,然后顺序打印2个语句,然后就是A的非静态块以及构造方法了。
最后来分析一个困扰我2天例子:
public class Class1 {
static {
new Class2();
System.out.println("666666666666666666");
}
{
System.out.println("99999999999999999");
}
public Class1() {
System.out.println("111111111111111111111");
}
public Class1(Class1 c1){
System.out.println("==============");
}
public Class1(Class2 c2){
System.out.println("++++++++++++++++++++");
}
public Class1(Class3 c3){
System.out.println("---------");
}
}
public class Class2 extends Class1{
}
public class Class3 extends Class2{
}
public class Test {
public static void main(String[] args) {
new Class1(new Class3());
}
}
执行结果:
99999999999999999
111111111111111111111
666666666666666666
99999999999999999
111111111111111111111
99999999999999999
---------
分析: