首页 > 学院 > 开发设计 > 正文

TIJ英文原版书籍阅读之旅——Chapter Five:Initialization & Cleanup

2019-11-15 00:33:21
字体:
来源:转载
供稿:网友
TIJ英文原版书籍阅读之旅——Chapter Five:Initialization & Cleanup 2015-06-10 19:55 by 海峰 :), ... 阅读, ... 评论, 收藏, 编辑

Methodoverloading

|_Distinguishingoverloadedmethods

Ifthemethodshavathesamename,howcanjavaknowwhichmethodyoumean?There'sasimplerule:Eachoverloadedmethodmusttakeauniquelistofargumenttypes.

|_OverloadingwithPRimitives

Wecanknowthattheconstantvalue5istreatedasint,soifanoverloadedmethodisavailablethattakesasint,itisused.Inallothercases,ifyouhavaadatatypethatissmallerthantheargumentinthemethod,thatdatatypeispromoted.charproducesasightlydifferenteffect,sinceifitdoesn'tfindanexactcharmatch,itispromotedtoint.

Supposethemethodstakenarrowerprimitivevalues.Ifyourargumentiswider,thenyoumustperformanarrowingconversionwithacast.Ifyoudon'tdothis,thecompilerwillissueanerrormessage.

|_Overloadingonreturnvalues

void f() {}int f() {return 1;}

Ifwejustwanttocallamethodforitssideeffect,suchas:

f();

howcanJavadeterminewhichf()shouldbecalled?Andhowcouldsomeonereadingthecodeseeit?BecauSEOfthissortofproblem,youcannotusereturnvaluetypestodistinguishoverloadedmethods.

Defaultconstructors

Ifyoucreateaclassthathasnoconstructors,thecompilerwillautomaticallycreateadefaultconstructorforyou.

Ifyoudefineanyconstructors(withorwithoutarguments),thecompilerwillnotsynthesizeoneforyou.

Whenyoudon'tputinanyconstructors,it'sasifthecompilersays,"Youareboundtoneedsomeconstructorsoletmemakeoneforyou."Butifyouwriteaconstructor,thecompilersays,"You'rewrittenaconstructorsoyouknowwhatyou'redoing;ifyoudidn'tputinadefaultit'sbecauseyoumeanttoleaveitout."

ThethiskeyWord

|_callingconstructorsfromconstructors

Whileyoucancalloneconstructorusingthis,youcannotcalltwo.Inaddition,theconstructorcallmustbethefirstthingyoudo,oryou'llgetacompilererrormessage.

|_themeaningofstatic

Itmeansthatthereisnothisforthatparticularmethod.Youcannotcallnon-staticmethodsfrominsidestaticmethod(althoughthereverseispossible),andyoucancallastaticmethodfortheclassitself,withoutanyobject.Infact,that'sprimarilywhatastaticmethodiffor.

Cleanup:finalizationandgarbagecollection

Whenthegarbagecollectorisreadytoreleasethestorageusedforyourobject,itwillfirstcallfinalize(),andonlyonthenextgarbage-collectionpasswillitreclaimtheobject'smemory.

InJava,objectsdonotalwaysgetgarbagecollected.Or,putanotherway:

1、Yourobjectsmightnotgetgarbagecollected.

2、Garbagecollectionisnotdestruction.

3、Garbagecollectionisonlyaboutmemory.

Youmightfindthatthestorageforanobjectnevergetsreleasedbecauseyourprogramnevernearsthepointofrunningoutofstorage.Ifyourprogramcompletesandthegarbagecollectornevergetsaroundtoreleasingthestorageforanyofyourobjects,thatstoragewillbereturnedtotheOperatingsystemenmasseastheprogramexits.Thisisagoodthing,becausegarbagecollectionhassomeoverhead,andifyouneverdoit,youneverincurthatexpense.

|_Whatisfinalize()for?

Itwouldseemthatfinalize()isinplacebecauseofthepossibilitythatyou'lldosomethingClikebyallocatingmemoryusingamechanismotherthanthenormaloneinJava.Thiscanhappenprimarilythoughnativemethods,whichareawaytocallnon-JavacodefromJava.CandC++aretheonlylanguagescurrentlysupportedbynativemethods,butsincetheycancallsubprogramsinotherlanguages,youcaneffectivelycallanything.Insidethenon-Javacode,C'smalloc()familyoffunctionmightbecalledtoallocatestorage,andunlessyoucallfree(),thatstoragewillnotbereleased,causingamemoryleak.Ofcourse,free()isaCandC++function,soyou'dneedtocallitinanativemethodinsideyourfinalize().

Afterreadingthis,youprobablygettheideathatyouwon'tusefinalize()much(JoshuaBlochgoesfurther:"finalizesareunpredictable,oftendangerous,andgenerallyunnecessary.").Youarecorrect;itisnottheappropriateplacefornormalcleanuptooccur.Sowhereshouldnormalcleanupbeperformed?

|_Youmustperformcleanup

Ifyouwantsomekindofcleanupperformedotherthanstoragerelease,youmuststillexplicitlycallanappropriatemethodinJava,whichistheequivalentofaC++destructorwithouttheconvenience.

Rememberthatneithergarbagecollectionnorfinalizationisguaranteed.IftheJVMisn'tclosetorunningoutofmemory,thenitmightnotwastetimerecoveringmemorythroughgarbagecollection.

|_Howagarbagecollectorworks

首先,JVM有多种实现形式,不同类型的JVM实现上会有所差别,速度、稳定性也不一样,因此应该辩证的看待下面的文字-:)

在一些JVM中,Java的堆与C++中的堆很是不同。C++中的堆就像一个大院子,每个对象占据一块地方。而Java中的堆则更像是一个传送带,因而加快了为对象分配内存的速度,就如同C++中的栈帧移动一般,随着"heappointer"的移动其分配内存的速度稍逊与栈(forJavaheap,there'salittleextraoverhead forbookkeeping,butit'snothinglikesearchingforstorage)。

一个简单且缓慢的垃圾回收方案是采用referencecounting。每个对象包含一个引用计数器,GC遍历整个对象列表,当它发现一个引用计数器为零时,释放该对象的内存。管理计数器引用在程序的整个生命周期中有小的常量的开销。缺点是彼此循环引用的对象虽为垃圾但是因其引用计数器非零,因此得不到释放。该方案通常被用来解释一种可能的垃圾回收机制,但是似乎从没有被任何JVM的具体实现采用过。

一个更快的方案是基于一种思想:non-dead对象必须最终能够被生存在栈上或是静态存储区上的引用所追踪到。这个链条可能穿越基层对象,从栈上和静态存储区上的所有引用开始,跟踪进引用指向的对象,然后跟踪对象里的所有引用,如此反复,可以找到所有生存的对象。值得注意的是,彼此循环引用对象的释放不在是问题了,它们不能被找到,自动成为了垃圾。

JVM采用适合的垃圾回收方案,可以根据不同的情况进行切换。两种主要的机制是"stop-and-copy"、"mark-and-sweep"。stop-and-copy方案暂停当前的程序,留下所有垃圾,只将生存的对象从一个堆拷贝到另一个堆中。mark-and-sweep方案一直被早期的Sun'sJVM采用,一般而言,它速度很慢,但是当垃圾很少甚至是没有垃圾产生的时候,其速度是很快的。mark-and-copy方案同样遵循从栈上或是静态存储区上的引用追踪对象的逻辑,每次它发现一个对象,对象就被设置一个标记,当mark程序执行完成后,sweep才能得到执行。sweep执行期间,死亡对象被释放。由于没有copy发生,如果收集器决定压紧碎片堆,只能通过移动对象的方式。

JVM监视GC的效率。如果所有对象长期生存,它切换到mark-and-sweep模式下工作。同样地,如果堆上的碎片变多,它切换回stop-and-copy模式。

JVM中还有很多额外的提速方法,比如just-in-time(JIT)compiler、HotSpot技术等。一部漫长的进化史啊:-)

ConstructorInitialization

There'sonethingtokeepinmind,however:Youaren'tprecludingtheautomaticinitialization,whichhappensbeforetheconstructorisentered.

所有的原生数据类型、对象引用(不包括局部变量,如果其未被初始化就使用的话,出现编译错误:variablemightnothavebeeninitialized)和那些在定义处清晰初始化的变量都被预先初始化为零。

|_Orderofinitialization

在类内部,变量初始化的顺序取决于它在类中定义的顺序。变量的定义可能分散地贯穿在方法的定义之间,但是变量在构造函数执行前被初始化。

|_staticdatainitialization

静态变量的初始化发生在类对象被创建的时候或者第一次静态访问发生的时候。

Tosummarizetheprocessofcreatinganobject,consideraclasscalledDog:

1、Eventhoughitdoesn'texplicitlyusethestatickeyword,theconstructorisactuallyastaticmethod.SothefirsttimeanobjectoftypeDogiscreated,orthefirsttimeastaticmethodorstaticfieldofclassDogisaccessed,theJavainterpretermustlocateDog.class,whichitdosebysearchingthroughtheclasspath.

2、AsDog.classisloaded(creatingaClassobject),allofitsstaticinitializersarerun.Thus,staticinitializationtakesplaceonlyonce,astheClassobjectisloadedforthefirsttime.

3、WhenyoucreateanewDog(),theconstructionprocessforaDogobjectfirstallocatesenoughstorageforaDogobjectontheheap.

4、Thisstorageiswipedtozero,automaticallysettingalltheprimitivesinthatDogobjecttotheirdefaultvalues(zerofornumberandtheequivalentforbooleanandchar)andthereferencestonull.

5、Anyinitializationsthatoccuratthepointoffielddefinitionareexecuted.

6、Constructorsareexecuted.Thismightactuallyinvolveafairamountofactivity,especiallywheninheritanceisinvolved.

|_Explicitstaticinitialization

Java中可以通过静态代码块的方式初始化一组静态变量。

语法形式:static{...}

它只会执行一次——thefirsttimeyoumakeanobjectofthatclassorthefirsttimeyouaccessastaticmemberofthatclass(evenifyounevermakeanobjectofthatclass).

|_Non-staticinstanceinitialization

Java提供一个简单的语法{...},称为实例初始化,用于初始化每个对象的非静态的变量,在构造函数之前执行。

Arrayinitialization

Java通过抛出运行期异常的方式防止数组访问越界,尽管这花费了一些时间,但是并没有方式来关闭它。为了网络安全和程序员的产出,Java设计者做出了他们认为值得的权衡。尽管你可能以你认为更高效的数组访问方式来写代码,这也是浪费时间的,因为自动的编译期和运行期优化将实现快速数组访问。

|_Variableargumentlists

与数组作为参数不同,变参列表的参数个数可以是零。

(END_XPJIANG).


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表