展望2011

2007-01-04 | java的初始化(3)【转载】

上一篇 / 下一篇  2007-04-27 18:00:03 / 个人分类:编程基础

在任何程序语言中,对成员的初始化和消除是非常重要的两个工作,而在java中由于有了垃圾回收器,我们一般都不需要对成员进行消除,绝大多数情况下,只需要注意初始化就可以了。
'EC/b~ }^}0
HB J;C M0以下是本人最近阅读《Thinking in java 3rd》所做的在java中对成员初始化的总结,结合了书上的讲解和自己的理解,错误之处请大家指出。51Testing软件测试网9?)c)C@J:Pd^\

{0mxPV0为了保证在变量使用前已经对变量进行初始化,java提供以下几种机制:51Testing软件测试网)jrbXwR;n:a.c.I }

A+_6[u `P01,    定义时直接赋值,如 int i=10;
!d&a4v I8b Y)eg02,    利用 {51Testing软件测试网Wv'[6F9?g F^7|
//初始化代码51Testing软件测试网%u;x)_#IoS9c}NG
 }
(n SL7z`1P#`G/y[03,    用static{ //初始化代码}51Testing软件测试网&Ftqce#e v
4,    用构造器(构造函数)初始化。51Testing软件测试网DX2k)b8};EJ U*B3|
5,    将变量赋予默认值,如 int,char型为 0,对象类型为null。51Testing软件测试网7c8x~(q9o@5Z
其实以上几种方式理解起来很容易,问题是JVM是按照什么样的顺序进行初始化的,也是很多刚学java的人犯晕的地方。
&T3Qd*AR nWtw0
|b%~9d3Gxa7n0
dw@ S~M2h01,单类中的初始化
3H no7l}-y j8yK\ u!l0最简单的是单个类,没有继承其他类。
FLJ|4c0看以下例子:51Testing软件测试网d+wqf9@#Z

4D h/z&nJ'D0package com.aaron.TIJTest.InitialationTest;
2uW e'`W)Pi0Yv,U`051Testing软件测试网:I+MKBdJ*m
public class InitialationTest {51Testing软件测试网7u]6pS6A
    51Testing软件测试网+O#v/eo _B}
    public static void main(String[] args) {51Testing软件测试网w)\;iY&_L r
        // TODO Auto-generated method stub51Testing软件测试网3c$M#p&PUhp
        Initialation ini = new Initialation(1,2,"aaa");
R"vw\_HQ0        System.out.println("\n");
PR r2?-T^ f!b-D0        Initialation.message();51Testing软件测试网s1O0V~o'xov
        System.out.println("\n\ncreate ini2");51Testing软件测试网3`i%y8VQj'?C
        Initialation ini2=new Initialation(3,4,"bbb");51Testing软件测试网 Z6@2^@'dGI-a k
    }
Z;Ib&O!]b O6J_0}51Testing软件测试网 K!e BB#O+wS.O g

3QT oCS*s [I0class Initialation{
@#~,Gt9b+`zv Ar0    int i=10;
p8}Z%]Q_1o0    {51Testing软件测试网2ArA Q5|
        System.out.println("i= "+i);51Testing软件测试网%Sr{7Zn(s3f c7G:S
        i=20;
)@-o2UFa0        System.out.println("i= "+i);
km;EA-S0    }
X k6LMA@3P0    String s;51Testing软件测试网-A)\_ L Kc f!r(l%}
    {51Testing软件测试网:p-l&Ez6o p0_
        System.out.println("s= "+s);51Testing软件测试网U\M(L+|;t1M
        s="abcd";51Testing软件测试网/K Z @X._&f
        System.out.println("s= "+s);
F'WJ5pH(Ao O6A0    }
8b SM4[CQ{'x5g6g/Aw0    static{
G5] pvNzQ0        System.out.println("static initialation block 1");51Testing软件测试网:g!m1c6p[|-Y
    }// static block 151Testing软件测试网8o&d8yUwL]
    
-U9Z/K^] C8UJc6G0    public Initialation(int x,int y,String s){51Testing软件测试网6g2e5X6l[
        System.out.println("Inside Constructor of Initialation");
W fk*j"X6Jg _|G0        i=x;
1z { |d&Y0        j=y;
#U8XC JgHpu[7@0        this.s=s;51Testing软件测试网9JD&x+\-r
        System.out.println("i= "+i);
t6d%Q%t*i1LI0        System.out.println("j= "+j);51Testing软件测试网.I5^A/_ p9w
        System.out.println("s= "+s);
Ew/HN3?*sgdd*Z0    }
V$}'T#C1? MAw0    public static void message(){
q Uh/T?r'f P4_JD7XN0        System.out.println("static method message()");51Testing软件测试网Xg|`[ }`
    }
+|-b2Ps5h~ m.g'f/?Sa0    51Testing软件测试网/P%g/]1ch&}g9dI d
    static{51Testing软件测试网-iBdK.{0J Ic}L#x
        System.out.println("static initialation block 2");51Testing软件测试网d vv#p'SlKC
    }//static block 2
|k H-qF7n0    int j=10;
4Q&Jzxc W5kSy0    {
#clnhD4}0        System.out.println("j= "+j);
kN(^-f.YH0        j=20;51Testing软件测试网RRYRp+E
        System.out.println("j= "+j);
vyN0B UL7^*l(s)b7QS1[0    }51Testing软件测试网nVi&r-MS}
    
&B?9f9}2?q3o%W0    
*e DHPq1\0}51Testing软件测试网7U VWS"wtu
输出结果是:51Testing软件测试网p AB5a YDgQ
static initialation block 1
3l@N@h JF0static initialation block 2
3Y$YrI-Di#f$N$P0i= 1051Testing软件测试网 r8o ZE%ty3j+K
i= 20
y.`gd4Ed b*~0s= null
I vO[5WN0s= abcd51Testing软件测试网YM8sy%G(^z;l
j= 10
-j4p8Z[__U|n2x0j= 20
l w;F4lC0Inside Constructor of Initialation51Testing软件测试网5P?1XO1`j z~
i= 1
.e#}:a7Dl e/c7LT0j= 251Testing软件测试网vV1pn*`S_
s= aaa51Testing软件测试网?I+bd2K@%qJ
51Testing软件测试网Pk6f s.{+?3e![T|
51Testing软件测试网(Hob0o3u byO
static method message()
(N0QLC2{?g\0
dW/Tl6p|v_6[)E0
3R#r8V q"Z#y-TG0create ini251Testing软件测试网s6r-z0z0h]z5~
i= 10
9@OB~drY m0i= 20
Y0J'PY [0aW:g5YM1N0s= null51Testing软件测试网F*b ` hK7C M:Z
s= abcd51Testing软件测试网k xQ rJ#D{i1S
j= 1051Testing软件测试网b&^tj8Sq@t
j= 2051Testing软件测试网^'nD/XP[c
Inside Constructor of Initialation
%~ wRx2REJK#W*w&i+O0i= 3
\D0EK5j#Jr*V0j= 4
#nx~ZE`]c([9R#]E0s= bbb
icOF I)zP"XT8j051Testing软件测试网wNVn"sz

5h-{4I*{%R0如果在main函数中注释掉51Testing软件测试网U"T7@6v$n[:^`l
// Initialation ini = new Initialation(1,2);51Testing软件测试网Mz%u@+G D
输出结果:51Testing软件测试网*b@e?0l3{ i$],I#w
51Testing软件测试网x;S4FVR!hJ8g

W5yE2_3IDd0static initialation block 151Testing软件测试网)K$H(jnw3~k&@ d
static initialation block 251Testing软件测试网$r:qA'd|M` \i
static method message()51Testing软件测试网&di(v zo

3HF7{T!SQ0
-vc*pB!xyH%p!_0create ini2
5ok7kTB;{0i= 1051Testing软件测试网-[ ^ m/e"nq
i= 2051Testing软件测试网F0B SQC#X Ja
s= null
2k'y;j:fXn)o0s= abcd
5R$@9Po7ka5Z j0j= 10
g"t2k ~v0j= 20
bU l-py:o0Inside Constructor of Initialation
iAIf[0i= 351Testing软件测试网3f6fx _*[W _4d1i
j= 4
`7Tiwq0s= bbb51Testing软件测试网$]zLJA.e
51Testing软件测试网 b$LEIB!rP
为什么呢?
t V(o6T&ZB0因为初始化的顺序是这样的:51Testing软件测试网[*aJbr(Kl Al x
1,    一旦第一次用new 创建一个对象或者调用这个类的静态函数(message()),编译器就寻找这个类的定义。
D#a/@ K\2TdS"C02,    找到这个类后,首先初始化类成员,按顺序执行static{}块的初始化,即
~q:N;^ R3}6F0先出现
#^l/TO,X;QUJ^0static initialation block 151Testing软件测试网t }*Do5G+@ z%p
static initialation block 251Testing软件测试网LX;pKGvN
如果不是第一次调用的话,static{}就不再执行,也就是说它只执行一次,从本例子中创建第二对象产生的结果可以看出来。
{6?#Y2~h&d03,    如果是调用静态函数的话,那么接下来就是直接调用该函数,然后就执行main中调用该静态函数的语句后面的语句。因此注释掉Initialation ini = new Initialation(1,2);就出现以上的结果。
z `9fCe0而如果是用new 创建对象的话(没有注释掉Initialation ini = new Initialation(1,2)),就先按照构造的过程,先在内存里分配足够大的空间给Initialation对象,并把所有的成员变量赋予初始值,如 i=0,s=null 。51Testing软件测试网\HN:\5n
4,    再接着就按照 i=10,{}这样的顺序初始化,两种的初始化按出现顺序进行,就算是构造函数夹在这些块的,也不执行构造函数的里头代码,而是先将构造函数外的初始化执行。 所以紧接着就出现i=10,i=20…这样的结果。
.B&p-M-y&W}3w,t`05,    再接着就是执行构造函数里头的代码。51Testing软件测试网mJmlQB5l%?;K
注意:先 static{},默认值,初始化语句:i=10…{…},最后才是构造函数。51Testing软件测试网bw%ZmK7Ij
以上是将main函数和类分离,如果将main放在Initialation类中,又会怎么样呢?
+QY,P\q2\t0
EW"x!z9?d.fq0public class Initialation {51Testing软件测试网9|Og lm agmc-p
51Testing软件测试网;M"?7fs}2y-n7xT2e][
    int i = 10;
7O2fZU k%U0    {51Testing软件测试网f'od,{K6t
        System.out.println("i= " + i);
?6D#{],d s-}S9e;N0        i = 20;51Testing软件测试网 T ab?;eP8]
        System.out.println("i= " + i);51Testing软件测试网 U:Y`+r[ F!@A
    }51Testing软件测试网G{I6Lh D%Z0e

-r B'Ks!x R,i0    String s;
"Q&i sj#n{K8uJ0X0    {
#~ Oz%N0rgM+Z0        System.out.println("s= " + s);
-c,_3DC$w7OF ^0        s = "abcd";
A0i(s:vC$u+]9u0        System.out.println("s= " + s);51Testing软件测试网x4d0?H5V7ImA
    }
~Rz0U0E-kA0    static {
)n M"TQ)tnv0        System.out.println("static initialation block 1");51Testing软件测试网(E^kkF
    }// static block 151Testing软件测试网6n@|p)s@{0yPL
51Testing软件测试网 o#tR O@
    public Initialation(int x, int y, String s) {
3K"I9K6e(M)w$A`.j0        System.out.println("Inside Constructor of Initialation");
+\Z#E;^$Q-?&k:F&W4Be0        i = x;
#? e mP4[0        j = y;51Testing软件测试网 B$\F,X_?
        this.s = s;51Testing软件测试网\6P2u_|lwmM {
        System.out.println("i= " + i);
9O+?#l'`!?H0        System.out.println("j= " + j);
W)QB.j;]9R+}8H&w5^"}0        System.out.println("s= " + s);51Testing软件测试网Q eCga)^`
    }
Yb+r-dx*{ Z6g051Testing软件测试网&eWU S4A:v Q7lS^4CL
    public static void message() {
K)N#VF4Vk&r0        System.out.println("static method message()");51Testing软件测试网@N%{f-XZrE
    }51Testing软件测试网"j_3I}(S

.Q-Ny }(_%Odc,t0    static {
gC%jyC!Ql0        System.out.println("static initialation block 2");51Testing软件测试网(a/\L6Q mF]6i6[/?s
    }// static block 251Testing软件测试网3t w0L]A

}By#]1U gi l0    int j = 10;51Testing软件测试网7Eio|P-`-n%Y:{
    {51Testing软件测试网q3h!zO;nM9a+}
        System.out.println("j= " + j);51Testing软件测试网 t.Z(d1gA-d i'p
        j = 20;
&u4QE+{1M,J2Ib0        System.out.println("j= " + j);51Testing软件测试网1s] l!Y,yj9C
    }
eTYzC pEw051Testing软件测试网R^7| O!A#dL.T
    public static void main(String[] args) {
#R_!y}#`3YZz0        // TODO Auto-generated method stub
c#{X`3ccC2O0        System.out.println("Inside main");51Testing软件测试网 [Zw(GHVQ-Ar;Gm
        Initialation ini = new Initialation(1, 2, "aaa");51Testing软件测试网qN}*a0a,\c}
        System.out.println("\n");
nF?u kr+V_0        Initialation.message();51Testing软件测试网#tu;T[ fYIY0UN;K.i
        
9H G0CMj/MX_0    }
]~!Q9]*_S0}51Testing软件测试网%T-q9|?:}
输出结果:
On@2gSF:v0static initialation block 1
,v7Fso(q/x0static initialation block 251Testing软件测试网}T!SE#N
Inside main
JD-_5j3m-~0i= 10
2D#W NN)@0i= 20
i @y1O)u V4eN0s= null51Testing软件测试网B3ni$l2?
s= abcd
+cH-Hj&T'`1RC,S0j= 10
4Uz!{ic4Ow6t0j= 2051Testing软件测试网VF#q6VqN#NRQG&x
Inside Constructor of Initialation51Testing软件测试网_/vX3tf)X(d
i= 1
7k6RQu3M0X0j= 251Testing软件测试网}.y|y,H
s= aaa51Testing软件测试网?O;o8w \ [0b#S N

#R D~;bSZX#i0a051Testing软件测试网.t0R R.fF7l1r,A'oX7X
static method message()51Testing软件测试网,D_wfm.fQ!lK
51Testing软件测试网y-c Msy
道理和以上说得一样。此时可以简单的将main方法当成普通的static方法。
8M? |*{ld(Y0
3WKuI RF051Testing软件测试网x.h]YleiZ
2,继承体系中的初始化
:_}(w4Q5h'k`q0实际上上面那个初始化也是属于本节中范围,因为任何class继承于Object, 上面的例子只不过为了便于理解而忽略了Object。
,QCH(CD0Hw W051Testing软件测试网y&W8b*r}8J8T,I
51Testing软件测试网2x.WE+Vq \
51Testing软件测试网 i-c9@3S:h1V}+s

7CI3_n } UY5g0看以下的例子:  
3E,hZ P#x0S0// InheritationInitialation.java
'rSB v9I/~{ e9D6n5?0public class InheritationInitialation {
he0Z dpHt4Y6B!q0    51Testing软件测试网QQLj1d3`
    public static void main(String[] args) {
8mk6_ n)S@4K0        // TODO Auto-generated method stub
1y PjaC)u|Q5z0        Rectangle.message();
-X!A+|;r&Ub%U+F0        System.out.println();
ea6I c.F c0        new Rectangle();51Testing软件测试网d*mCmdQ
        System.out.println();
:QG%sa W:|0        new Rectangle("another object");51Testing软件测试网y'W"aP:Z[0m
    }
YwX&{J#Eg051Testing软件测试网sc }Z9i!^
}
I\S|0T0
#UC0fy!a2Gh4z@s0class Shape{
3d ne8gM0    static{51Testing软件测试网1w%_'U!koGE
        System.out.println("Shape:static block");
8[oHO+s~0    }51Testing软件测试网T OIQl
    {
+|fm3ID:G2D0        System.out.println("Shape:non-static block");
n1P aA4y7s2iw(n0    }
f'|?7M#_6lj0u+Hd0    public Shape(){51Testing软件测试网!gk a"|9q;S zx
        System.out.println("Shape Constructor");
GX*I0I1N'\0    }51Testing软件测试网$?T9{[@
    public Shape(String s){
Y-ajS f'L6_0        System.out.println("Shape Constructor with s: "+s);51Testing软件测试网 iF0yBc G
        
MM7S)T+DXV4_%IX sY0    }51Testing软件测试网Q0T z0V3Ax-Q/j
}
,dH0EX0s+n2{0class Line extends Shape{51Testing软件测试网%h%z/]c6YU;m/mA
    static{
0k~2u5I `l0        System.out.println("Line :static block");51Testing软件测试网5d2Z:F)n!ANv6I(z$n
    }
U&u xE3U(iV%s0Ii0    {
i'VXV)S0        System.out.println("Line :non-static block");51Testing软件测试网!zQo%T+|3@$I
    }51Testing软件测试网&H dU`hi
    public Line(){
T\-o9H'`~ W+N[)^H0        System.out.println("Line Constructor");
n8[6\ m(MLM0    }
A4e Yb[,p*j?0    public Line(String s){51Testing软件测试网vqoU8uwEM
        System.out.println("Line Constructor with s: "+s);51Testing软件测试网zmG)n:Z H
        
1M&V y vd h-T0    }51Testing软件测试网.o"~C9Xt*d
}51Testing软件测试网.qnl epN"Ho9q8u$W

M;@@:g:fs/ls0class Rectangle extends Line{51Testing软件测试网8L'xp][S8[
    static{
^SzNs @Q/r0        System.out.println("Rectangle:static block");
D7F4J_~T8b0    }
)c~sj As_!Cv+v"c0    {
&k*kri5KZ.j?kfE1@0        System.out.println("Rectangle:non-static block");51Testing软件测试网%\6YvW"y7?
    }
9zu:?;@"V L0r:{Q0    public Rectangle(){51Testing软件测试网{4P SN:p;wM+SG
        System.out.println("Rectangle Constructor");51Testing软件测试网8s9V+WT4D:om1i
    }51Testing软件测试网;Y0d8lH/]7h7j.p
    public Rectangle(String s){51Testing软件测试网:a-T*v.Vi%T7yb
        super(s);51Testing软件测试网/Pu` r(i
        System.out.println("Rectangle Constructor with s: "+s);    51Testing软件测试网'`5F0Y{!`)|0W|
        51Testing软件测试网JH E_Nc
    }
(x%jaHl+z8S S-T:W2}0    public static void message(){
K7{#n8^;B:b0        System.out.println("static method in Rectangle");
2Y-a2Y"tVd;K0    }
q4R U$O-G0}51Testing软件测试网E{!v4C B&i.e+g p O
51Testing软件测试网 X8{5gqA9gm*UU
结果是:
h.E9J1uk Rc0Shape:static block
@7Qku \0e i0Line :static block51Testing软件测试网Tk*` [2VAQ!W
Rectangle:static block
aG)r-y8^;[l$DU8\VQ0static method in Rectangle51Testing软件测试网z!? x;R&u!|
51Testing软件测试网Z N N-y$v
Shape:non-static block
xl*^9x^0Shape Constructor
;} ftz6DyX0Line :non-static block
;F7vz*|0I w0Line Constructor
i~rDB4q0Rectangle:non-static block
h!h R|6`F9]#g0Rectangle Constructor51Testing软件测试网w!jU3?5Of-?:\{aD

*o8fy Ds M+n0Shape:non-static block51Testing软件测试网 Q-aX,kGj3n
Shape Constructor
FoY k;V5\|u1q`0Line :non-static block51Testing软件测试网 xVn _ b-S8su
Line Constructor with s: another object
$Mx1D:v^0Rectangle:non-static block51Testing软件测试网UF^ ] Kh q"K$V I$P
Rectangle Constructor with s: another object
!@0wnWv UI,R D,d$Y051Testing软件测试网\\HUwPF
这里要注意两个问题:
uV2p;xP:a"XN01,    第一次用到类时都是初始化static{}或是static变量,因为编译器此时并不知道你是否需要创建对象,只知道你此时要用到类。51Testing软件测试网'WR7rfgOg9?G
2,    在子类的构造函数中,如果你没有显式的调用父类的构造函数,编译器隐式的调用父类的default构造函数。
"}/@6C LG2b,GM?0也就是说在Rectangle类中的public Rectangle(){}应该是这样的:51Testing软件测试网4] J,Q*E8W E$Kv
Public Rectangle(){51Testing软件测试网%`Qn$sAs6z9onY
        Super();//编译器自动添加51Testing软件测试网!{v9Hv+j.I^,i
          System.out.println("Rectangle Constructor");
0ch d`!M051Testing软件测试网(E0gg0uf{7P:Nm
}
(N0h%~y*|p0如果父类中没有default构造函数且在子类的构造函数没有显式的调用父类的别的构造函数,则编译出错。
+N&l%Lh![ A n j m0该规则是为了确保子类中从父类继承过来的字段得到初始化。
8Ma]!F1~#C9h#h8e0e0
-}e!c"Ve@0知道这两点后,再结合单类初始化中的知识,就可以理解继承体系中的初始化顺序:51Testing软件测试网0b2J qCIw
以下从程序开始讲起(个人的理解)51Testing软件测试网DHJ)I5~Jn
1,    运行程序java InheritationInitialation, 编译器先找main函数,由于main函数是属于类InheritationInitialation, 所以先对类51Testing软件测试网sa]8A X*F e9|kYd
InheritationInitialation进行初始化(本例中没有其他的初始化,就只有一个main函数),初始化完毕后调用执行main里头的代码;
w$F#t7uG02,  遇到Rectangle.message(); 是属于Rectangle类,找到        Rectangle类(至于怎么找,交给编译器),发现继承
MB;f-MG"H#Z H[r0了Line类,而Line类又继承了Shape类。51Testing软件测试网kKG!o,onf/[)Pz~
因此先执行Shape类的static{}块的初始化,再执行Line类的Static{}初始化,最后执行Rectangle类的static{}初始化。这是第一步,因为此时只知道要用到这些类,但不清楚是否要创建一个对象。51Testing软件测试网y;}Y5X\7Q/y4U
完成了这些初始化之后,才回来执行
@uisl]/{7n0zo0Rectangle.message()里头的代码。51Testing软件测试网J,MQA.CC] `B

.U.ye r6l#q03,接下来执行System.out.println();紧接着遇到new Rectangle();此时要用到Rectangle类,由于这不是第一次使用Rectangle,所以static{}块的初始化代码就不再运行了(可以在main中注释掉Rectangle.message();同样是先输出三个Static{}里头的内容). 
F*h~_FO My7r;j)\0遇到new Rectangle() 是先按照单类中的初始化顺序51Testing软件测试网;Bw X \SnGW
? 初始化Object类中的初始化代码 51Testing软件测试网 k4D~0J-e
? 然后跑到Shape类按顺序进行成员初始化,最后才执行构造器Shape(){}中的代码。51Testing软件测试网4Z-w B*Ps$c7@]
? 接着回到Line类,按顺序进行成员初始化,最后执行构造器Line(){}代码,51Testing软件测试网d'Cia]c!x? hZ.I
? 接着执行Rectangle类的初始化,最后执行Rectangle()代码。51Testing软件测试网W Y.|M;fr-q0M@
至此完成该语句new Rectangle()的执行。
$Z.E} v8e.V0要从年龄最“老“的那个类开始初始化,51Testing软件测试网 ?qW4U+N g
4,    执行new Rectangle("another object");顺序同3中描述一样,不过执行的构造函数不一样罢了。
v0J2Yx-h(~uHh05,    程序结束。51Testing软件测试网4} N y#ED(h
51Testing软件测试网Y_8`xy-?)E!G`5s
基本的流程就是这样:
&ks"z"EHg A)D!o/H01,    递归调用基类的构造函数,先创建根,然后是下一级直到最后一级的构造函数。
s'X \1?"^M8CSF] dm02,    每调用一个构造函数呢,先按其所在类的类成员按顺序初始化(按单类里头那样),然后才执行构造函数里面的代码。
z*W4f7q?sp051Testing软件测试网IPA[p&X'CV
51Testing软件测试网-~5B L ]/bnp
以上的内容是看了thinking in java 3rd 之后,对初始化顺序有个彻底的理解,总结了一下,错误之处请指出。51Testing软件测试网,kkY"hp8D+p#x9s#?0c

TAG: JAVA 初始化 编程基础

 

评分:0

我来说两句

Open Toolbar