对象的生成过程

好长时间没看java了,有些东西得复习一下。

现在存在两个类Father和Child,如果我们new  Child();或者new Child("李明");这个过程发生了什么?

先看Father:

 1 public class Father{
2 static{
3 System.out.println("Father_jingtaichushihuakuai");
4 }
5 public static String static_str="Father_jingtaiziduan";
6 {
7 System.out.println("Father_chushihuakuai");
8 }
9 public String str="Father_ziduan";
10 public Father(){
11 System.out.println("Father_wucangouzaohanshu");
12 }
13 public Father(String str){
14 System.out.println("Father_youcangouzaohanshu");
15 }
16 }

再看Child:

 1 public class Child extends Father{
2 public static String static_str="Child_jingtaiziduan";
3 static{
4 System.out.println("Child_jingtaichushihuakuai");
5 }
6 public String str="Child_ziduan";
7 {
8 System.out.println("Child_chushihuakuai");
9 }
10 public Child(){
11 System.out.println("Child_wucangouzaohanshu");
12 }
13 public Child(String str){
14 System.out.println("Child_youcangouzaohanshu");
15 }
16 public static void main(String[] args) {
17 new Child();
18 System.out.println("×××××××分割线×××××××");
19 new Child("abc");
20 System.exit(0);
21
22 }
23 }

再看结果:

 1 Father_jingtaichushihuakuai
2 Child_jingtaichushihuakuai
3 Father_chushihuakuai
4 Father_wucangouzaohanshu
5 Child_chushihuakuai
6 Child_wucangouzaohanshu
7 ×××××××分割线×××××××
8 Father_chushihuakuai
9 Father_wucangouzaohanshu
10 Child_chushihuakuai
11 Child_youcangouzaohanshu


分析原因之前,先说明一点,Father类默认继承Object.

附:

Father.class文件
 1 // class version 50.0 (50)
2 // access flags 33
3 public class com/ibeen/test/Father {
4
5 // compiled from: Father.java
6
7 // access flags 9
8 public static Ljava/lang/String; static_str
9
10 // access flags 1
11 public Ljava/lang/String; str
12
13 // access flags 8
14 static <clinit>()V
15 L0 (0)
16 LINENUMBER 5 L0
17 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
18 LDC "Father_jingtaichushihuakuai"
19 INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
20 L1 (4)
21 LINENUMBER 7 L1
22 LDC "Father_jingtaiziduan"
23 PUTSTATIC com/ibeen/test/Father.static_str : Ljava/lang/String;
24 L2 (7)
25 LINENUMBER 3 L2
26 RETURN
27 MAXSTACK = 2
28 MAXLOCALS = 0
29
30 // access flags 1
31 public <init>()V
32 L0 (0)
33 LINENUMBER 12 L0
34 ALOAD 0
35 INVOKESPECIAL java/lang/Object.<init>()V
36 L1 (3)
37 LINENUMBER 9 L1
38 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
39 LDC "Father_chushihuakuai"
40 INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
41 L2 (7)
42 LINENUMBER 11 L2
43 ALOAD 0
44 LDC "Father_ziduan"
45 PUTFIELD com/ibeen/test/Father.str : Ljava/lang/String;
46 L3 (11)
47 LINENUMBER 13 L3
48 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
49 LDC "Father_wucangouzaohanshu"
50 INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
51 L4 (15)
52 LINENUMBER 14 L4
53 RETURN
54 L5 (17)
55 LOCALVARIABLE this Lcom/ibeen/test/Father; L0 L5 0
56 MAXSTACK = 2
57 MAXLOCALS = 1
58
59 // access flags 1
60 public <init>(Ljava/lang/String;)V
61 L0 (0)
62 LINENUMBER 15 L0
63 ALOAD 0
64 INVOKESPECIAL java/lang/Object.<init>()V
65 L1 (3)
66 LINENUMBER 9 L1
67 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
68 LDC "Father_chushihuakuai"
69 INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
70 L2 (7)
71 LINENUMBER 11 L2
72 ALOAD 0
73 LDC "Father_ziduan"
74 PUTFIELD com/ibeen/test/Father.str : Ljava/lang/String;
75 L3 (11)
76 LINENUMBER 16 L3
77 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
78 LDC "Father_youcangouzaohanshu"
79 INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
80 L4 (15)
81 LINENUMBER 17 L4
82 RETURN
83 L5 (17)
84 LOCALVARIABLE this Lcom/ibeen/test/Father; L0 L5 0
85 LOCALVARIABLE str Ljava/lang/String; L0 L5 1
86 MAXSTACK = 2
87 MAXLOCALS = 2
88 }
Child.class文件
  1 // class version 50.0 (50)
2 // access flags 33
3 public class com/ibeen/test/Child extends com/ibeen/test/Father {
4
5 // compiled from: Child.java
6
7 // access flags 9
8 public static Ljava/lang/String; static_str
9
10 // access flags 1
11 public Ljava/lang/String; str
12
13 // access flags 8
14 static <clinit>()V
15 L0 (0)
16 LINENUMBER 4 L0
17 LDC "Child_jingtaiziduan"
18 PUTSTATIC com/ibeen/test/Child.static_str : Ljava/lang/String;
19 L1 (3)
20 LINENUMBER 6 L1
21 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
22 LDC "Child_jingtaichushihuakuai"
23 INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
24 L2 (7)
25 LINENUMBER 3 L2
26 RETURN
27 MAXSTACK = 2
28 MAXLOCALS = 0
29
30 // access flags 1
31 public <init>()V
32 L0 (0)
33 LINENUMBER 12 L0
34 ALOAD 0
35 INVOKESPECIAL com/ibeen/test/Father.<init>()V
36 L1 (3)
37 LINENUMBER 8 L1
38 ALOAD 0
39 LDC "Child_ziduan"
40 PUTFIELD com/ibeen/test/Child.str : Ljava/lang/String;
41 L2 (7)
42 LINENUMBER 10 L2
43 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
44 LDC "Child_chushihuakuai"
45 INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
46 L3 (11)
47 LINENUMBER 13 L3
48 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
49 LDC "Child_wucangouzaohanshu"
50 INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
51 L4 (15)
52 LINENUMBER 14 L4
53 RETURN
54 L5 (17)
55 LOCALVARIABLE this Lcom/ibeen/test/Child; L0 L5 0
56 MAXSTACK = 2
57 MAXLOCALS = 1
58
59 // access flags 1
60 public <init>(Ljava/lang/String;)V
61 L0 (0)
62 LINENUMBER 15 L0
63 ALOAD 0
64 INVOKESPECIAL com/ibeen/test/Father.<init>()V
65 L1 (3)
66 LINENUMBER 8 L1
67 ALOAD 0
68 LDC "Child_ziduan"
69 PUTFIELD com/ibeen/test/Child.str : Ljava/lang/String;
70 L2 (7)
71 LINENUMBER 10 L2
72 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
73 LDC "Child_chushihuakuai"
74 INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
75 L3 (11)
76 LINENUMBER 16 L3
77 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
78 LDC "Child_youcangouzaohanshu"
79 INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
80 L4 (15)
81 LINENUMBER 17 L4
82 RETURN
83 L5 (17)
84 LOCALVARIABLE this Lcom/ibeen/test/Child; L0 L5 0
85 LOCALVARIABLE str Ljava/lang/String; L0 L5 1
86 MAXSTACK = 2
87 MAXLOCALS = 2
88
89 // access flags 9
90 public static main([Ljava/lang/String;)V
91 L0 (0)
92 LINENUMBER 19 L0
93 NEW com/ibeen/test/Child
94 INVOKESPECIAL com/ibeen/test/Child.<init>()V
95 L1 (3)
96 LINENUMBER 20 L1
97 GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
98 LDC "\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u5206\u5272\u7ebf\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7\u00d7"
99 INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
100 L2 (7)
101 LINENUMBER 21 L2
102 NEW com/ibeen/test/Child
103 LDC "abc"
104 INVOKESPECIAL com/ibeen/test/Child.<init>(Ljava/lang/String;)V
105 L3 (11)
106 LINENUMBER 22 L3
107 ICONST_0
108 INVOKESTATIC java/lang/System.exit(I)V
109 L4 (14)
110 LINENUMBER 76 L4
111 RETURN
112 L5 (16)
113 LOCALVARIABLE args [Ljava/lang/String; L0 L5 0
114 MAXSTACK = 2
115 MAXLOCALS = 1
116 }

排除Object,来看打印结果

得出一个小小的结论:

 

    new Child()这个过程

  1. 父类的静态块
  2. 子类的静态块
  3. 父类的非静态块
  4. 父类的无参构造方法
  5. 子类的非静态块
  6. 子类的无参构造方法      

    new Child("abc")这个过程:

  1. 父类的非静态块
  2. 父类的无参构造方法
  3. 子类的非静态块
  4. 子类的无参构造方法

这两个过程的差别在于第一个过程的中的前2个步骤,事实上这两个步骤和这两个过程没有任何关系。

静态变量和静态块在声明的时候仅被初始化一次。和创建对象与否无关。

可能会有人问,那么静态变量什么时候初始化呢?

我们来看Child.class文件中

  static <clinit>()V
L0 (0)
LINENUMBER 4 L0
LDC "Child_jingtaiziduan"
PUTSTATIC com/ibeen/test/Child.static_str : Ljava/lang/String;
L1 (3)
LINENUMBER 6 L1
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Child_jingtaichushihuakuai"
INVOKEVIRTUAL java/io/PrintStream.println(Ljava/lang/String;)V
L2 (7)
LINENUMBER 3 L2
RETURN
MAXSTACK = 2
MAXLOCALS = 0

这一区域只执行一次,顺序很明显了:先初始化静态变量, 然后再执行静态块。

事实上是在定义类的时候,静态变量和静态块哪个在前面哪个先执行。

同样的方法看非静态变量和非静态块同样如此。

关于静态部分,可以得出:

  1. 父类的静态变量的初始化和静态块的执行先于子类
  2. 同一个类中,静态变量和静态块哪个先定义哪个先初始化(执行)

ps:静态变量和静态块的初始化在什么时候执行,我也不知道,我猜,在jvm加载的时候,你猜呢?

关于对象的生成,可以得出:

  1. 父类的非静态块或者非静态变量,哪个先定义哪个先初始化(执行);
  2. 父类的构造函数;
  3. 子类的非静态块或者非静态变量,哪个先定义哪个先初始化(执行);
  4. 子类的构造函数;

ps:如果子类被调用的构造方法中没有显示调用父类的有参构造方法,将默认调用父类的无参构造方法

posted on 2011-11-19 18:28  ibeen  阅读(383)  评论(0)    收藏  举报

导航