详解Java的初始化与清理
大家都知道,Java是站在巨人的肩上成功的,它是在C&C++的基础上进一步的开发,投入面向对象开发的怀抱。Java吸取了很多以前的教训,加入自己很多独创的方式。在程序语言发展初期,许多C程序员经常忘记初始化变量,在程序结束后也经常忘记对创建的数据类型进行释放内存,造成内存泄漏。这些"不安全"的编程方式当然需要程序员有良好的编程习惯,但如果编程语言能够加入自动清理与初始化的工作,这回大大降低开发成本。随着技术的发展,C++语言引入了构造器(constructor),即在创建对象自动调用的初识方法,Java语言采用这一方法,并加入垃圾回收器,负责自动回收用户创建的内存,进一步降低程序员的开发成本。
Java的初始化与构造器
创建Java的对象最普遍发的方法是使用new方法,如下所示。而创建对象必须使用构造器,构造器实际就是Java对象初始化的方法,用户可以在该方法中添加自定义初始化行为。
Objectobj=newObject();//左侧为声明对象,右侧为实际创建一个对象
构造器它是一个隐含为静态的无返回值的方法,名称与类名相同,编译期会自动调用该方法。如果用户没有创建构造器,编译期会为你自动生成一个默认构造器。总之,构造器个数至少有一个。构造器可以有多个,它可以用户自己选择如何初始化对象,这里是使用重载(Overload)的方法。如下所示:
packagecom.thinkinjava.initialization;
importstaticcom.thinkinjava.util.Print.*;
classTree{
intheight;
Tree(){
print("Plantingaseedling");
height=0;
}
Tree(intinitialHeight){
height=initialHeight;
print("CreatingnewTreethatis"+
height+"feettall");
}
voidinfo(){
print("Treeis"+height+"feettall");
}
voidinfo(Strings){
print(s+":Treeis"+height+"feettall");
}
}
publicclassOverloading{
publicstaticvoidmain(String[]args){
for(inti=0;i<5;i++){
Treet=newTree(i);
t.info();
t.info("overloadedmethod");
}
//Overloadedconstructor:
newTree();
}
}
Java的初始化顺序
既然讲到Java初始化,那肯定要关注Java的初始化顺序,这涉及到一些继承的知识,首先看一个实例:
packagecom.thinkinjava.multiplex;
importstaticcom.thinkinjava.util.Print.print;
/**
*初始化顺序
*
*/
//形状
classInsect{
privateinti=9;
protectedintj;
privateintk=priInit("Insect.kinitialized");
Insect(){
print("i="+i+",j="+j);
j=39;
}
privatestaticintx1=priInit("staticInsect.x1initialized");
staticintpriInit(Strings){
print(s);
return47;
}
}
classInitOrderextendsInsect{
privateinti=10;
privateintk=priInit("InitOrder.kinitialized");
publicInitOrder(){
print("k="+k);
print("j="+j);
}
privatestaticintx2=priInit("staticInitOrder.x2initialized");
publicstaticvoidmain(String[]args){
print("InitOrderconstructor");
InitOrderx=newInitOrder();
}
}
Output:
staticInsect.x1initialized
staticInitOrder.x2initialized
InitOrderconstructor
Insect.kinitialized
i=9,j=0
InitOrder.kinitialized
k=47
j=39
如上所示,当运行该Java程序时,首先访问程序入口,即InitOrder.main()方法,于是类加载器加载InitOrder.class类文件,而对它的加载过程中,通过extends关键字可知该类有个父类,于是加载该父类,如果该父类还有它自身的父类,继续加载,然后执行最高一层类的static初始化,然后是其子类,依次执行,最后所有的类的已加载完成,开始执行main方法:在main方法中开始创建对象,对象被创建之后,虚拟机会为其分配内存,主要用来存放对象的实例变量及其从父类继承过来的实例变量(即使这些从父类继承过来的实例变量有可能被隐藏也会被分配空间)。在为这些实例变量分配内存的同时,这些实例变量也会被赋予默认值。在内存中创建对象后,开始调用父类的构造器,父类的构造器能够使用super调用或被编译期自动调用,父类在执行构造器语句之前,会对父类实例变量按照次序进行初始化。父类完成父类子对象的初始化后,子类开始的顺序执行,先实例变量初始化,然后执行构造器语句。最后整个对象构造完成。
Java的对象与清理
Java的显著优点就是Java有良好的垃圾清理机制,C++中创建对象,使用对象后,需要使用delete操作符删除对象,就会调用对应的析构函数。而Java中没有析构函数,Java的finalize()并不是类似C++的析构函数,Java的finalize()只是用来回收本地方法(c/c++)占用的内存(调用本地方法类似free)。通常意义上来讲,Java程序员只需创建对象,而不需我们自己去销毁对象,因为垃圾回收机制会帮我们回收对象,虽然不知道什么时候回收,是否会被回收。
然后可能会出现这种情况,类可能要在生命周期内执行一些必需的清理活动,这就需要程序员自己书写清理方法,在清理方法中必须注意清理顺序,即其顺序与初始化顺序相反,为防止出现异常,可以将清理动作放入finally中。如实例所示:
importstaticcom.thinkinjava.util.Print.print;
/**
*确保正确清理
**/
//形状
classShape{
Shape(inti){
print("Shapeconstructor");
}
//处理
voiddispose(){
print("Shapedispose");
}
}
classCircleextendsShape{
Circle(inti){
super(i);
print("Circleconstructor");
}
voiddispose(){
print("Circledispose");
super.dispose();
}
}
//三角形
classTriangleextendsShape{
Triangle(inti){
super(i);
print("Triangleconstructor");
}
voiddispose(){
print("Triangledispose");
super.dispose();
}
}
classLineextendsShape{
privateintstart,end;
Line(intstart,intend){
super(start);
this.start=start;
this.end=end;
print("DrawingLine:"+start+","+end);
}
voiddispose(){
//擦除线条
print("ErasingLine:"+start+","+end);
super.dispose();
}
}
publicclassCADSystemextendsShape{
privateCirclec;
privateTrianglet;
privateLine[]lines=newLine[3];
publicCADSystem(inti){
super(i+1);
for(intj=0;j=0;i--){
lines[i].dispose();
}
super.dispose();
}
publicstaticvoidmain(String[]args){
CADSystemx=newCADSystem(47);
try{
//程序编码与异常处理
}finally{
x.dispose();
}
}
Output:
Shapeconstructor
Shapeconstructor
DrawingLine:0,0
Shapeconstructor
DrawingLine:1,1
Shapeconstructor
DrawingLine:2,4
Shapeconstructor
Circleconstructor
Shapeconstructor
Triangleconstructor
Combinedconstructor
CADSystem.dispose()
Triangledispose
Shapedispose
Circledispose
Shapedispose
ErasingLine:2,4
Shapedispose
ErasingLine:1,1
Shapedispose
ErasingLine:0,0
Shapedispose
Shapedispose*/
以上就是详解Java的初始化与清理的详细内容,更多关于Java的初始化与清理的资料请关注毛票票其它相关文章!