闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ゆ繝鈧柆宥呯劦妞ゆ帒鍊归崵鈧柣搴㈠嚬閸欏啫鐣峰畷鍥ь棜閻庯絻鍔嬪Ч妤呮⒑閸︻厼鍔嬮柛銊ョ秺瀹曟劙鎮欏顔藉瘜闂侀潧鐗嗗Λ妤呭锤婵犲洦鐓曢悗锝庡亝鐏忕増绻涢懝閭﹀殭闁宠鍨归埀顒婄秵閸嬧偓闁归攱妞藉缁樼瑹閸パ傜敖闂佺ǹ顑嗛惄顖炲箠閻旂⒈鏁嶆繛鎴炵懄閻濈兘姊洪崷顓℃闁哥姵顨婇幃鈥斥槈閵忊€斥偓鍫曟煟閹邦厼绲婚柍閿嬫閺屾洟宕卞Ο鐑樿癁闂佸搫鑻粔鐑铰ㄦ笟鈧弻娑㈠箻閸楃偛顬嬬紓浣戒含閸嬨倕鐣烽崡鐐╂婵☆垳銆嬬槐閬嶆⒒娴e憡鍟炲〒姘殜瀹曘垺銈i崘銊﹁緢闂佹寧妫冮弫顕€宕戦幘璇茬濠㈣泛锕f竟鏇㈡⒒娴e憡鍟炴繛璇х畵瀹曟粌鈽夐姀鐘插亶闂佸綊妫块悞锕傚磹閻㈠憡鐓曢煫鍥ㄦ惄濡茬ǹ霉濠婂牏鐣烘慨濠冩そ閺屽懘鎮欓懠璺侯伃婵犫拃鍐惧殶闁逞屽墲椤煤閹达箑纭€闁告劕妯婇崵鏇灻归悩宸剾闁轰礁娲︾换婵婎槼闁稿氦娅曠粋宥夊箚椤€崇秺閺佹劙宕堕埞搴撳亾婵犲啩绻嗛柟缁樺笧婢ф稑菐閸パ嶈含妞ゃ垺绋戦~婵嬵敆娴e洠鏅犲铏圭磼濮楀棙鐣烽悗鍏夊亾缂佸顑欏ḿ鏍ㄧ箾瀹割喕绨荤€瑰憡绻傞埞鎴︽偐閹绘巻鍋撻幖渚婄稏閹兼番鍔嶉埛鎴犵磼鐎n偒鍎ラ柛搴㈠姍閺岀喖宕ㄦ繝鍕啓濡炪倧绲块崑鎾舵崲濠靛顫呴柨婵嗘閵嗘劕顪冮妶鍡楃仴閻庢凹鍣i獮鎴﹀閵堝懎鑰垮┑鐐村灦閻熝囧储娴犲鈷戦悷娆忓缁舵煡鏌涘锝呬壕缂傚倷闄嶉崝宀勨€﹂悜钘夎摕鐎广儱鐗滃銊╂⒑閸涘﹥灏扮€光偓缁嬭法鏆︾憸鐗堝笒閸ㄥ倹銇勯弮鍌氫壕婵炲牓绠栧娲传閸曨剙绐涢梺鍝ュУ閹告儳顕h閸┾偓妞ゆ巻鍋撻柍瑙勫灴椤㈡瑩寮妶鍕繑闂備礁鎲¢幐濠氭儎椤栫偑鈧礁鈻庨幘鍐茶€垮┑鐐村灦閻熴垽骞忓ú顏呯厽闁绘ê鍘栭懜顏堟煕閺傝儻瀚伴柍璇茬Ч楠炲洭鎮ч崼銏犲箥闂備礁鎲¢崹顖炲磹閺嶎偀鍋撳鐐 (0) +1 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤濠€閬嶅焵椤掑倹鍤€閻庢凹鍙冨畷宕囧鐎c劋姹楅梺鍦劋閸ㄥ綊宕愰悙鐑樺仭婵犲﹤鍟扮粻鑽も偓娈垮枟婵炲﹪寮崘顔肩<婵炴垶鑹鹃獮鍫熶繆閻愵亜鈧倝宕㈡禒瀣瀭闁割煈鍋嗛々鍙夌節闂堟侗鍎愰柣鎾存礃缁绘盯宕卞Δ鍐唺缂備胶濮垫繛濠囧蓟瀹ュ牜妾ㄩ梺鍛婃尰閻熝呭垝鐠囧樊鍚嬪璺猴功閿涚喖姊绘笟鍥у缂佸顕划濠氼敍閻愭潙鈧敻鏌ㄥ┑鍡涱€楅柡瀣洴閹嘲鈻庡▎鎴犳殼闂佽鍠楅〃濠囧极閹邦厽鍎熼柍鈺佸暟娴滃爼姊绘担铏瑰笡闁规瓕顕х叅闁绘梻鍘ч拑鐔衡偓骞垮劚椤︻垶鎮″☉妯忓綊鏁愰崨顔兼殘闂佽绻戦幐鎼佸煘閹达附鍊烽柤纰卞墮椤e爼姊洪幖鐐插缂傚秴锕ら敃銏℃媴閾忓湱锛滅紓鍌欓檷閸ㄧ懓顕i鈧弻锟犲焵椤掍焦缍囬柍瑙勫劤娴滅偓鎱ㄥΟ鐓庝壕閻庢熬鎷� (0) +1 闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ょ紓宥咃躬瀵鎮㈤崗灏栨嫽闁诲酣娼ф竟濠偽i鍓х<闁绘劦鍓欓崝銈囩磽瀹ュ拑韬€殿喖顭烽幃銏ゅ礂鐏忔牗瀚介梻浣告贡閾忓酣宕板Δ鍜佹晛闁哄稁鍘介埛鎴犵磼鐎n偒鍎ラ柛搴㈠姍閺屾盯濡搁妷锕€浠村Δ鐘靛仜閸燁偉鐏冮梺閫炲苯澧撮柛鈹垮劜瀵板嫭绻涢悙顒傗偓濠氭煟鎼搭垳绉甸柛鎾寸〒缁絽螖娴i绠氶梺缁樺姦娴滄粓鍩€椤掍礁濮嶇€殿喗褰冮オ浼村醇閻旇渹绨甸梻浣芥硶閸犳挻鎱ㄩ幘顔藉珔闁绘柨鍚嬮悡銉︾節闂堟稒锛嶆俊鎻掓憸缁辨帡鎮崨顖溞滈梺鍝勮閸斿矂鍩為幋锕€骞㈡慨妤€鐗忕粈濠冪節绾版ɑ顫婇柛瀣閳ь剚鍑归崰姘i幇鏉跨閻庢稒锚椤庢捇姊洪崨濠勭畵閻庢氨鍏橀崺鈧い鎺嗗亾闁活厼鍊垮璇测槈閵忕姈鈺呮煏婢诡垰鍟伴崢浠嬫煟鎼淬埄鍟忛柛鐘崇墵閳ワ箓鏌ㄧ€b晝绠氶梺褰掓?缁€渚€鎮″☉銏$厱閻忕偛澧介悡顖滅磼閵娿倗鐭欐慨濠勭帛閹峰懘宕ㄩ棃娑氱Ш鐎殿喚鏁婚、妤呭磼濠婂懐鍘梻浣侯攰閹活亞鈧潧鐭傚顐﹀磼閻愬鍙嗛梺缁樻礀閸婂湱鈧熬鎷� (0) +1
闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ゆ繝鈧柆宥呯劦妞ゆ帒鍊归崵鈧柣搴㈠嚬閸欏啫鐣峰畷鍥ь棜閻庯絻鍔嬪Ч妤呮⒑閸︻厼鍔嬮柛銊ョ秺瀹曟劙鎮欏顔藉瘜闂侀潧鐗嗗Λ妤呭锤婵犲洦鐓曢悗锝庡亝鐏忕増绻涢懝閭﹀殭闁宠鍨归埀顒婄秵閸嬧偓闁归攱妞藉缁樼瑹閸パ傜敖闂佺ǹ顑嗛惄顖炲箠閻旂⒈鏁嶆繛鎴炵懄閻濈兘姊洪崷顓℃闁哥姵顨婇幃鈥斥槈閵忊€斥偓鍫曟煟閹邦厼绲婚柍閿嬫閺屾洟宕卞Ο鐑樿癁闂佸搫鑻粔鐑铰ㄦ笟鈧弻娑㈠箻閸楃偛顬嬬紓浣戒含閸嬨倕鐣烽崡鐐╂婵☆垳銆嬬槐閬嶆⒒娴e憡鍟炲〒姘殜瀹曘垺銈i崘銊﹁緢闂佹寧妫冮弫顕€宕戦幘璇茬濠㈣泛锕f竟鏇㈡⒒娴e憡鍟炴繛璇х畵瀹曟粌鈽夐姀鐘插亶闂佸綊妫块悞锕傚磹閻㈠憡鐓曢煫鍥ㄦ惄濡茬ǹ霉濠婂牏鐣烘慨濠冩そ閺屽懘鎮欓懠璺侯伃婵犫拃鍐惧殶闁逞屽墲椤煤閹达箑纭€闁告劕妯婇崵鏇灻归悩宸剾闁轰礁娲︾换婵婎槼闁稿氦娅曠粋宥夊箚椤€崇秺閺佹劙宕堕埞搴撳亾婵犲啩绻嗛柟缁樺笧婢ф稑菐閸パ嶈含妞ゃ垺绋戦~婵嬵敆娴e洠鏅犲铏圭磼濮楀棙鐣烽悗鍏夊亾缂佸顑欏ḿ鏍ㄧ箾瀹割喕绨荤€瑰憡绻傞埞鎴︽偐閹绘巻鍋撻幖渚婄稏閹兼番鍔嶉埛鎴犵磼鐎n偒鍎ラ柛搴㈠姍閺岀喖宕ㄦ繝鍕啓濡炪倧绲块崑鎾舵崲濠靛顫呴柨婵嗘閵嗘劕顪冮妶鍡楃仴閻庢凹鍣i獮鎴﹀閵堝懎鑰垮┑鐐村灦閻熝囧储娴犲鈷戦悷娆忓缁舵煡鏌涘锝呬壕缂傚倷闄嶉崝宀勨€﹂悜钘夎摕鐎广儱鐗滃銊╂⒑閸涘﹥灏扮€光偓缁嬭法鏆︾憸鐗堝笒閸ㄥ倹銇勯弮鍌氫壕婵炲牓绠栧娲传閸曨剙鍋嶉梺鎼炲妼缂嶅﹪骞忛幋锔藉亜闁稿繗鍋愰崢顏呯節閵忥絾纭鹃柣妤€妫濆畷婵嗩潩閼哥數鍘介柟鍏兼儗閸犳牕顕i鑺ュ弿濠电姴鎳忛鐘电磼椤旇姤顥堢€规洖宕灃闁逞屽墴椤㈡梻鈧稒岣跨粻楣冩煕椤愩倕鏋戞い銉ョ墦閺屸€崇暆鐎n剛鏆ら悗瑙勬礃閿曘垽銆侀弮鍫濈妞ゆ帒鍊烽柇顖炴⒒閸屾瑧顦﹂柟纰卞亰閹本寰勫畝鈧粈濠偯归敐鍛棌闁搞倖娲橀妵鍕即濡も偓娴滈箖鎮楃憴鍕闁绘牕鍚嬫穱濠囨倻閽樺娼婇梺缁樏畷顒勊夊鑸碘拻濞撴埃鍋撻柍褜鍓涢崑娑㈡嚐椤栨稒娅犻柟缁㈠枟閻撴盯鎮橀悙鎻掆挃闁靛棙甯¢弻宥堫檨闁告挶鍔庣槐鐐哄幢濞戞ḿ锛涢梺鍛婁緱閸垶鎮炴繝鍐︿簻闁规儳宕悘顏堟煟閹惧啿鏆i柡宀嬬畱铻e〒姘煎灡閳绘挸鈹戦垾鍐茬骇闁诡喖鍊垮璇差吋閸ャ劌鐝伴梺鑲┾拡閸庣柉顦抽柕鍥у婵偓闁愁厼绻愮紞濠呮闁哄鐗冮弲婵堝婵傚憡鐓忓┑鐐茬仢閸旀﹢鏌涚€c劌鐏查柡灞糕偓宕囨殕闁逞屽墴瀹曚即骞囬鍓х暥闂佺粯姊婚崢褔宕归崒娑栦簻闁哄啫鍊甸幏鈩冪箾閻撳酣鍙勯柡宀嬬稻閹棃濡舵惔銏㈢Х婵犵數鍋涘鍫曟晝閵忕姷鏆﹂柡鍥╁枔闂勫嫰鏌℃径濠冾棞婵炲樊鍙冮妴浣割潩鐠鸿櫣鍔﹀銈嗗笒鐎氼剟鎷戦悢鍏肩叆闁绘柨鎼瓭闂佺粯甯掗悘姘跺Φ閸曨垰绠抽柟瀛樼箥娴犻箖姊洪幖鐐测偓鏇犵矓瑜版帒钃熼柡鍥╁枎缁剁偞绻涢幋鐐跺妞ゆ洝浜槐鎾存媴闂堟稑顬堝銈庡幖閸㈡煡锝炶箛鎾佹椽顢旈崟顏嗙倞闂備礁鎲″ú锕傚礈濞嗘垹鐜绘繛鎴欏灪閳锋垹绱掔€n偒鍎ラ柛搴㈠灴閺屾稓鈧絻鍔岄埀顒佺☉铻為柕蹇嬪€栭埛鎴犵磽娴e顏呮叏婢舵劖鐓曢幖瀛樼☉閳ь剚绻傞悾鐑藉箛閺夊灝鐎銈嗗姧缁茶棄顕i崹顔规斀闁宠棄妫楅悘锝夋煕濡姴瀚々鎻捨旈敐鍛殲闁稿﹤鐏氶幈銊ノ熼悡搴濆闁诲孩鐔幏锟�闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閹冣挃闁硅櫕鎹囬垾鏃堝礃椤忎礁浜鹃柨婵嗙凹缁ㄥジ鏌熼惂鍝ョМ闁哄矉缍侀、姗€鎮欓幖顓燁棧闂備線娼уΛ娆戞暜閹烘缍栨繝闈涱儐閺呮煡鏌涘☉鍗炲妞ゃ儲鑹鹃埞鎴炲箠闁稿﹥顨嗛幈銊╂倻閽樺锛涢梺缁樺姉閸庛倝宕戠€n喗鐓熸俊顖濆吹濠€浠嬫煃瑜滈崗娑氭濮橆剦鍤曢柟缁㈠枛椤懘鏌eΟ鑽ゅ灩闁搞儯鍔庨崢閬嶆⒑閺傘儲娅呴柛鐔村妽缁傛帡鏁傞崜褏锛滃銈嗘⒒閹虫挻鏅堕幓鎹涘酣宕惰闊剟鏌熼鐣屾噰妞ゃ垺妫冨畷鐔煎Ω閵夈倕顥氶梻浣告惈缁嬩線宕㈤懖鈺冪焼濠㈣泛鏈崰鎰扮叓閸ャ劍绀€闁搞劍绻傞埞鎴︽偐鐎圭姴顥濈紓浣哄缂嶄線寮婚敐鍛傜喖鎮滃Ο閿嬬亞婵犵妲呴崑鍛垝閹炬剚娼栭柧蹇撴贡閻捇鏌涢埄鍐炬當妞ゅ繐鐡ㄧ换娑㈠醇閻斿摜顦伴梺鍝勭焿缂嶄線鐛Ο灏栧亾濞戞瑡缂氭い锔垮嵆濮婃椽宕崟顓犱紘闂佸摜濮甸悧鐘差嚕婵犳艾鐐婃い鎺嶇劍濞呭洭姊洪柅鐐茶嫰婢ф挳鏌熼鏂よ€块柡灞芥椤撳ジ宕卞▎蹇撶疄闂傚倷绶氬ḿ褔鎮ч崱娑樼閻庯綆鍠栫壕鍧楁煛閸愩劎澧涢柣鎾寸洴閹﹢鎮欐0婵嗘闂侀€炲苯澧紒璇插€块、姘舵晲婢跺﹪鍞堕梺鍝勬川閸嬬喖顢欓崶顒佺厵闁兼祴鏅炶棢闂侀€炲苯澧€殿喛娉涜灒濠电姴娲﹂埛鎺楁煕鐏炲墽鎳呮い锔肩畵閺岀喓鍠婇崡鐐板枈閻庢鍠氶弫濠氥€佸Δ鍛<婵犲﹤鎳愰崢顖炴⒒娴d警鏀伴柟娲讳簽缁骞嬮敂钘変簵闂佺偨鍎查崜姘舵偄閸℃稒鍋i柛婵嗗婵炲洭鏌涢鐘插姎闁告垹濞€楠炴牕菐椤掆偓婵′粙鏌i幘瀵告噰婵﹥妞介、姗€濡歌閺嗙娀姊洪崫鍕靛剭闁稿﹥绻堝璇差吋閸ャ劌鐝伴梺鑲┾拡閸撴盯顢欐繝鍕=濞达絼绮欓崫娲煙閻熺増鎼愰柣锝囧厴楠炴帡骞嬮鐔峰厞婵$偑鍊栭崹鐓幬涢崟顒傤洸闁诡垎灞惧瘜闁诲函缍嗘禍婊堫敆閵忕姭鏀芥い鏍ㄥ搸閸嬨垽鏌″畝瀣?濞寸媴濡囬幏鐘诲箵閹烘埈娼涢梻鍌欑劍閻綊宕愬┑鍫笉闁哄稁鍘奸拑鐔兼煥濠靛棙鍟掗柣鏂跨殱閺嬪酣鏌熼鍡楀閸炴煡姊婚崒娆愮グ婵☆偄瀚板畷顖涘閺夋垹鐛ラ梺鍝勭▉閸樺ジ鎷戦悢鍏肩叆婵犻潧妫Σ鍝ョ磼椤愩垻效闁哄本绋撴禒锔剧磼閵忥紕鏆﹂梺璇插绾板秹鎯勯姘兼綎闁绘垶蓱婵粓鏌熷▓鍨珮婵″樊鍠氱槐鎾存媴閸撳弶楔闂佽桨鐒﹂幃鍌炵嵁閹达箑顫呴柣姗嗗亝閺傗偓闂備焦鎮堕崕顕€寮插┑瀣剨闁割偁鍎查埛鎴犵磼鐎n偄顕滄繝鈧幍顔炬/闁哄娉曟晥闂佽鍠楅敃銏ょ嵁濡偐纾兼俊顖炴敱鐎氬ジ姊绘担鍛婂暈缂佽鍊婚埀顒佸嚬閸欏啴寮鍜佸悑濠㈣泛顑囬崢鍗炩攽閳藉棗鐏″ù婊€绮欏畷鎴﹀閵堝棛鍘撻梺闈涱檧闂勫嫰藟閸懇鍋撶憴鍕闁挎洏鍨介妴浣糕枎閹惧啿绨ユ繝銏n嚃閸ㄦ澘煤閿曞倹鍋傞柡鍥ュ灪閻撴瑩鏌熸担鍐╃彧婵炲懎鎳庨埞鎴︽晬閸曨偄浠橀梺瀹狀潐閸ㄥ潡銆佸▎鎾崇畾鐟滃秹鐛€n亖鏀芥い鏃傘€嬮弨缁樹繆閻愭壆鐭欐鐐插暣閹粓鎸婃径宀勭崜闂備礁婀辨灙閻庡灚甯″畷顒勫Ω閳哄倵鎷绘繛杈剧悼閸庛倝宕甸埀顒勬⒑閹肩偛鈧牠鎮ч悩鑽ゅ祦闊洦绋掗弲鎼佹煥閻曞倹瀚�>>

正在阅读:提高 Java 代码的性能提高 Java 代码的性能

2005-08-15 14:40 出处: 作者:Eric Allen 责任编辑:xietaoming

  尾递归转换能加快应用程序的速度,但不是所有的 JVM 都会做这种转换 

  很多算法用尾递归方法表示会显得格外简明。编译器会自动把这种方法转换成循环,以提高程序的性能。但在 Java 语言规范中,并没有要求一定要作这种转换,因此,并不是所有的 Java 虚拟机(JVM)都会做这种转换。这就意味着在 Java 语言中采用尾递归表示可能导致巨大的内存占用,而这并不是我们期望的结果。Eric Allen 在本文中阐述了动态编译将会保持语言的语义,而静态编译则通常不会。他说明了为什么这是一个重要问题,并提供了一段代码来帮助判断您的即时(JIT)编译器是否会在保持语言语义的同时做尾递归代码转换。

  尾递归及其转换

  相当多的程序包含有循环,这些循环运行的时间占了程序总运行时间的很大一部分。这些循环经常要反复更新不止一个变量,而每个变量的更新又经常依赖于其它变量的值。

  如果把迭代看成是尾递归函数,那么,就可以把这些变量看成是函数的参数。简单提醒一下:如果一个调用的返回值被作为调用函数的值立即返回,那么,这个递归调用就是尾递归;尾递归不必记住调用时调用函数的上下文。 

  由于这一特点,在尾递归函数和循环之间有一个很好的对应关系:可以简单地把每个递归调用看作是一个循环的多次迭代。但因为所有可变的参数值都一次传给了递归调用,所以比起循环来,在尾递归中可以更容易地得到更新值。而且,难以使用的 break 语句也常常为函数的简单返回所替代。  

  但在 Java 编程中,用这种方式表示迭代将导致效率低下,因为大量的递归调用有导致堆栈溢出的危险。  

  解决方案比较简单:因为尾递归函数实际上只是编写循环的一种更简单的方式,所以就让编译器把它们自动转换成循环形式。这样您就同时利用了这两种形式的优点。  

  但是,尽管大家都熟知如何把一个尾递归函数自动转换成一个简单循环,Java 规范却不要求做这种转换。不作这种要求的原因大概是:通常在面向对象的语言中,这种转换不能静态地进行。相反地,这种从尾递归函数到简单循环的转换必须由 JIT 编译器动态地进行。  

  要理解为什么会是这样,考虑下面一个失败的尝试:在 Integers 集上,把 Iterator 中的元素相乘。  

  因为下面的程序中有一个错误,所以在运行时会抛出一个异常。但是,就象在本专栏以前的许多文章中已经论证的那样,一个程序抛出的精确异常(跟很棒的错误类型标识符一样)对于找到错误藏在程序的什么地方并没有什么帮助,我们也不想编译器以这种方式改变程序,以使编译的结果代码抛出一个不同的异常。  

  清单 1. 一个把 Integer 集的 Iterator 中的元素相乘的失败尝试 

import java.util.Iterator; 

public class Example { 

  public int product(Iterator i) { 
    return productHelp(i, 0); 
  } 

  int productHelp(Iterator i, int accumulator) { 
    if (i.hasNext()) { 
      return productHelp(i, accumulator * ((Integer)i.next()).intValue()); 
    } 
    else { 
      return accumulator; 
    } 
  } 

  注意 product 方法中的错误。product 方法通过把 accumulator 赋值为 0 调用 productHelp。它的值应为 1。否则,在类 Example 的任何实例上调用 product 都将产生 0 值,不管 Iterator 是什么值。  

  假设这个错误终于被改正了,但同时,类 Example 的一个子类也被创建了,如清单 2 所示: 

  清单 2. 试图捕捉象清单 1 这样的不正确的调用 

import java.util.*; 

class Example { 

  public int product(Iterator i) { 
    return productHelp(i, 1); 
  } 

  int productHelp(Iterator i, int accumulator) { 
    if (i.hasNext()) { 
      return productHelp(i, accumulator * ((Integer)i.next()).intValue()); 
    } 
    else { 
      return accumulator; 
    } 
  } 


// And, in a separate file: 

import java.util.*; 

public class Example2 extends Example { 
  int productHelp(Iterator i, int accumulator) { 
    if (accumulator < 1) { 
      throw new RuntimeException("accumulator to productHelp must be >= 1"); 
    } 
    else { 
      return super.productHelp(i, accumulator); 
    } 
  } 

  public static void main(String[] args) { 
    LinkedList l = new LinkedList(); 
    l.add(new Integer(0)); 
    new Example2().product(l.listIterator()); 
  } 

  类 Example2 中的被覆盖的 productHelp 方法试图通过当 accumulator 小于“1”时抛出运行时异常来捕捉对 productHelp 的不正确调用。不幸的是,这样做将引入一个新的错误。如果 Iterator 含有任何 0 值的实例,都将使 productHelp 在自身的递归调用上崩溃。  

  现在请注意,在类 Example2 的 main 方法中,创建了 Example2 的一个实例并调用了它的 product 方法。由于传给这个方法的 Iterator 包含一个 0,因此程序将崩溃。  

  然而,您可以看到类 Example 的 productHelp 是严格尾递归的。假设一个静态编译器想把这个方法的正文转换成一个循环,如清单 3 所示:  

  清单 3. 静态编译不会优化尾调用的一个示例

int productHelp(Iterator i, int accumulator) { 
    while (i.hasNext()) { 
      accumulator *= ((Integer)i.next()).intValue(); 
    } 
    return accumulator; 
  } 

  于是,最初对 productHelp 的调用,结果成了对超类的方法的调用。超方法将通过简单地在 iterator 上循环来计算其结果。不会抛出任何异常。  

  用两个不同的静态编译器来编译这段代码,结果是一个会抛出异常,而另一个则不会,想想这是多么让人感到困惑。  


 
  您的 JIT 会做这种转换吗?

  因此,如清单 3 中的示例所示,我们不能期望静态编译器会在保持语言语义的同时对 Java 代码执行尾递归转换。相反地,我们必须依靠 JIT 进行的动态编译。JIT 会不会做这种转换是取决于 JVM。  

  要判断您的 JIT 会否转换尾递归的一个办法是编译并运行如下小测试类:  

  清单 4. 判断您的 JIT 能否转换尾递归 

public class TailRecursionTest { 

  private static int loop(int i) { 
    return loop(i); 
  } 

  public static void main(String[] args) { 
    loop(0); 
  } 

  我们来考虑一下这个类的 loop 方法。这个方法只是尽可能长时间地对自身作递归调用。因为它永远不会返回,也不会以任何方式影响任何外部变量,因此如清单 5 所示替换其代码正文将保留程序的语义。  

  清单 5. 一个动态转换 

public class TailRecursionTest { 

  private static int loop(int i) { 
    while (true) { 
    } 
  } 

  public static void main(String[] args) { 
    loop(0); 
  } 

  而且,事实上这也就是足够完善的编译器所做的转换。  

  如果您的 JIT 编译器把尾递归调用转换成迭代,这个程序将无限期地运行下去。它所需的内存很小,而且不会随时间增加。  

  另一方面,如果 JIT 不做这种转换,程序将会很快耗尽堆栈空间并报告一个堆栈溢出错误。  

  我在两个 Java SDK 上运行这个程序,结果令人惊讶。在 SUN 公司的 Hotspot JVM(版本 1.3 )上运行时,发现 Hotspot 不执行这种转换。缺省设置下,在我的机器上运行时,不到一秒钟堆栈空间就被耗尽了。  

  另一方面,程序在 IBM 的 JVM(版本 1.3 )上咕噜噜运行时却没有任何问题,这表明 IBM 的 JVM 以这种方式转换代码。  

  总结 

  记住:我们不能寄希望于我们的代码会总是运行在会转换尾递归调用的 JVM 上。因此,为了保证您的程序在所有 JVM 上都有适当的性能,您应始终努力把那些最自然地符合尾递归模式的代码按迭代风格编写。  

  但是请注意:就象我们的示例所演示的那样,以这种方式转换代码时很容易引入错误,不论是由人工还是由软件来完成这种转换。  

  其实从网上发现这样的文章并不难,希望大家在遇到问题时都能学会如何处理

  学习的过程就是学会学习方法的过程,难道不是吗? 

关注我们

最新资讯离线随时看 聊天吐槽赢奖品
闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閹冣挃闁硅櫕鎹囬垾鏃堝礃椤忎礁浜鹃柨婵嗙凹缁ㄥジ鏌熼惂鍝ョМ闁哄矉缍侀、姗€鎮欓幖顓燁棧闂傚倸娲らˇ鐢稿蓟閵娿儮鏀介柛鈩冪懃椤も偓婵$偑鍊曠换鎺撴叏妞嬪孩顫曢柟鐑橆殔閻掑灚銇勯幒宥堝厡缂佲檧鍋撻梻浣呵归張顒勩€冮崱娑樻闁逞屽墴濮婄粯鎷呴搹鐟扮闁藉啳浜幉鎼佸级閸喗娈婚梺绯曟杹閸嬫挸顪冮妶鍡楀潑闁稿鎸婚妵鍕即閵娿儱绠诲┑鈥冲级閸旀瑩鐛鈧獮鍥ㄦ媴閻熸澘鍘為梻浣告惈椤︻垶鎮ч崟顖氱鐎光偓閸曨偄鍤戦梺纭呮彧闂勫嫰鍩涢幋锔界厱婵犻潧妫楅鈺呮煛閸℃ḿ鎳囬柡宀嬬到铻栭柍褜鍓涢埀顒佺煯閸楀啿鐣峰ú顏勭劦妞ゆ帊闄嶆禍婊堟煙鏉堝墽绋荤痪顓炲缁辨帡骞囬鐔叉嫽闂侀€炲苯澧い鏃€鐗犲畷浼村即閻樻彃鐏婂┑鐐叉閹稿爼鍩€椤戣法顦︽い顐g矒閸┾偓妞ゆ帒瀚粻鏍ㄧ箾閸℃ɑ灏伴柛銈嗗灴閺屾盯濡搁敂閿婵炲瓨绮撶粻鏍蓟濞戔懇鈧箓骞嬪┑鍥╀簮闂備浇銆€閸嬫挸霉閻樺樊鍎愰柣鎾卞劜缁绘盯骞嬮悘娲讳邯椤㈡棃鍩℃导鍗炵秺閹晛鈻庤箛鏂挎缂佺偓鍎抽崥瀣Φ閸曨垰鍗抽柣鎰綑濞咃綁姊虹拠鏌ョ崪濠碘€虫喘閸┾偓妞ゆ帊绶¢崯蹇涙煕閿濆骸娅嶇€规洘鍨剁换婵嬪炊瑜忛悾娲⒑閸愬弶鎯堥柛鐔稿婢规洟宕楅梻瀵哥畾濡炪倖鐗滈崑鐐哄极闁秵鍊垫慨姗嗗厵閸嬨垺鎱ㄦ繝鍌ょ吋鐎规洘甯掗埢搴ㄥ箣閿濆洨宕堕梻鍌欒兌鏋い鎴濇噹铻炴繝闈涙閺嗭箓鏌熺€涙ḿ濡囨俊鎻掔墦閺屾洝绠涙繛鎯т壕闁惧浚鍋掗崥鍛攽閿涘嫬浜奸柛濠冪墵閹兾旈崘顏嗙厯闂佸湱鍎ら崹鐔煎几瀹ュ鐓熸俊顖濆亹鐢盯鏌i幘瀵告噮缂佽鲸鎸婚幏鍛存濞戞矮鎮i梻浣告惈椤戝洭宕伴弽顓炶摕闁挎繂顦粻濠氭倵闂堟稒鍟為柛锝庡弮濮婃椽妫冨☉娆愭倷闁诲孩纰嶅姗€顢氶敐澶樻晪闁逞屽墴瀹曟椽鍩€椤掍降浜滈柟鐑樺灥椤忔挳鏌℃担绋款仾缂佺粯鐩畷鍗炍旈崘顏嗘毉缂傚倸鍊搁崐鐟扮暆閹间礁钃熼柣鏃傚帶缁犮儲銇勯弮鍌楁嫛闁哄棭鍙冨铏圭磼濡闉嶉梺鑽ゅ暀閸パ呭姦濡炪倖甯掗崐褰掑吹閳ь剟鏌f惔銏犲毈闁哥姵顨婂鑼崉娴f洘妫冨畷銊╊敇閻愭潙鍔掗梻鍌欑劍閹爼宕曢鈧顒佺瑹閳ь剙鐣烽幋锕€绠婚柤鎼佹涧閺嬪倿姊洪崨濠冨闁告挻鐩弫宥咁潨閳ь剙顫忓ú顏勫窛濠电姴鍟伴崣鍡欑磽娴e壊妲搁柣鏍с偢閻涱噣骞嬮敃鈧~鍛存煟濮楀棗浜濋柡鍌楀亾闂備浇顕ч崙鐣岀礊閸℃ḿ顩查柣鎰劋閺咁剚绻濇繝鍌氭殜闁衡偓娴犲鐓熼柟閭﹀墮缁狙勩亜閵壯冧槐闁哄本鐩顕€鍩€椤掑嫭鍋嬮柣妯款嚙閺勩儵鏌曡箛瀣偓鏇㈠础閹惰姤鐓熼柡鍐ㄦ处椤忕娀鏌i敃鈧悧鎾愁潖閸濆嫅褔宕惰娴煎牆鈹戦悙鏉垮皟闁告劏鏅滈惁搴㈢節绾板纾块柛瀣灴瀹曟劘顦寸紒杈╁仱閸┾偓妞ゆ帊妞掔换鍡樸亜閹扳晛鐏╂い蹇婃櫇閳ь剝顫夐幐鍝モ偓姘緲椤繐煤椤忓嫬绐涙繝鐢靛Т鐎氀勬叏閸パ€鏀介柣鎰絻閹垿鏌i悢婵嗗閻濆爼鏌¢崶鈺佹灁缂佲檧鍋撴繝娈垮枟閿曗晠宕㈡ィ鍐ㄥ偍闁汇垹鎲¢埛鎴犵棯椤撶偞濯兼繛鍏煎姍閺屾盯寮幘鍓佹殼閻庤娲熷ḿ褔鍩㈡惔銊ョ闁绘ḿ顣槐鏌ユ⒒娴h櫣甯涢柣鐔村灲瀹曟垿骞樼紒妯煎幈闂侀潧枪閸庢娊宕洪敐鍥e亾濞堝灝鏋涙い顓㈡敱娣囧﹪骞栨担鍝ュ幐闂佺ǹ鏈惌顔捐姳娴犲鈷掑ù锝呮嚈瑜版帒瀚夋い鎺戝€婚惌娆撴煙鏉堟儳鐦滈柡浣稿€块弻銊╂偆閸屾稑顏�闂傚倸鍊搁崐鎼佸磹閹间礁纾归柟闂寸绾惧綊鏌熼梻瀵割槮缁炬儳缍婇弻鐔兼⒒鐎靛壊妲紒鐐劤缂嶅﹪寮婚悢鍏尖拻閻庨潧澹婂Σ顔剧磼閻愵剙鍔ょ紓宥咃躬瀵鏁愭径濠勵吅闂佹寧绻傞幉娑㈠箻缂佹ḿ鍘辨繝鐢靛Т閸婂綊宕戦妷鈺傜厸閻忕偠顕ф慨鍌溾偓娈垮枟閹告娊骞冨▎寰濆湱鈧綆浜欐竟鏇㈡⒑閸涘﹦缂氶柛搴ゆ珪缁嬪顓兼径瀣幐閻庡箍鍎辨鎼佺嵁濡ゅ懏鐓熼柟鎯х摠缁€鍐煏閸パ冾伃妤犵偛娲畷婊勬媴閼介攱鍨圭槐鎾存媴閹绘帊澹曢梻渚€鈧偛鑻晶鎵磼鏉堛劌娴柟顔界懇椤㈡鍩€椤掑嫬绀夐柕鍫濇缁犲墽鐥銏╂缂佲檧鍋撻柣搴㈩問閸犳牠鈥﹂悜钘夌畺闁靛繈鍊栭崑鍌炲箹鏉堝墽鎮奸柡鍡曞嵆濮婄粯鎷呴搹鐟扮濡炪們鍔岄幊姗€骞冭楗即宕楅悙顒傛创鐎规洜鍠栭、姗€鎮╃喊澶屽簥闂傚倷娴囬鏍垂鎼淬劌绀冮柨婵嗘閻﹁京绱撻崒姘偓椋庢閿熺姴闂い鏇楀亾鐎规洖缍婇獮搴ㄦ寠婢跺矈鍞归梻渚€娼х换鎺撴叏椤撶倣锝夊醇閵夛妇鍘棅顐㈡处濞叉牕鏆╂俊鐐€栭幐鎼佸箹椤愶箑鐓橀柟杈鹃檮閸婄兘鏌涘▎蹇f▓婵☆偆鍋熺槐鎾存媴閾忕懓绗¢柣銏╁灡椤ㄥ牏鍒掔€n喖绠抽柟鎯х埣濡绢噣姊洪崨濠勨槈閼瑰矂鏌熼柨瀣仢婵﹥妞藉畷銊︾節閸曨厾鏆ら梺璇插閸戝綊宕滈悢绗衡偓渚€寮崼婢劑鏌嶉崫鍕偓濠氬储闁秵鐓欓柤鍦瑜把呯磼閺屻儳鐣虹€殿喗濞婇、妤佺瑹閸ヮ煈鍟嶉梻浣虹帛閸旀牞銇愰崘顔兼辈婵炲棙鍔戞禍婊勩亜閹板墎鎮奸柣顓熷浮閺屾盯鍩為幆褌澹曞┑锛勫亼閸婃牜鏁幒鏂哄亾濮樼厧澧扮紒顔碱煼瀵粙濡歌椤旀洟姊虹化鏇炲⒉閽冮亶鎮樿箛锝呭箻缂佽鲸甯¢幃顏勨枎韫囨柨顦╅梺缁樻尰濞叉﹢濡甸崟顖f晣闁绘棃顥撴禒鎾⒑閸濆嫷鍎嶉柛濠冾殜楠炲骞栨担鐟颁罕闂佸壊鍋呯换鍕閹绢喗鈷戦悗鍦濞兼劙鏌涢妸銉﹀仴妤犵偛鍟埢搴ㄥ箻閺夋垶顓绘俊鐐€栫敮濠囨倿閿曞倸绐楅柡宥庡亞绾句粙鏌涚仦鍓ф噮閻犳劒鍗抽弻娑㈡偐瀹曞洤鈷堢紓渚囧枟濡啫鐣锋總绋垮嵆闁绘劖顔栧Σ鎾⒒娴e憡璐¢柛搴涘€濋妴鍐川椤栨粈绗夋繝鐢靛У绾板秹宕戦敐澶嬬厱闁靛鍠曠花濠氭煢閸曨偁鍋㈤柡宀€鍠栭幊鐐哄Ψ閿旂虎妲梻浣哥枃椤宕归崸妤€绠栨繛鍡樻尭缁狙囨煙鐎电ǹ小闁瑰鍏樺缁樻媴閾忓箍鈧﹪鏌¢崨顔俱€掗柍褜鍓氱喊宥咁熆濮椻偓椤㈡岸鏁愭径妯绘櫇闂佹寧娲嶉崑鎾剁磼閳ь剟宕橀埞澶哥盎闂佸搫鍟崐鐟扳枍閺囥垺鐓曟繛鍡楃箲椤ユ粓鏌嶇憴鍕伌闁诡喒鏅濈槐鎺懳熸繝姘殬濠电姷顣藉Σ鍛村磻閸涘瓨鍋¢柍鍝勫閿涘倿姊绘担铏瑰笡瀹€锝呮健瀹曟垿濡搁敂缁㈡锤濠电姴锕ら悧濠囨偂閵夆晜鐓涢柛灞剧☉椤曟粓鏌熼姘卞ⅵ闁哄本鐩顕€骞樼紒姗嗏偓宥夋⒑闁稓鈹掗柛鏂跨Ф閹广垹鈹戠€n亞顦ㄩ梺宕囨嚀閵囨﹢鎼规惔銊︾厽閹兼番鍊ゅḿ鎰箾閹绘帞绠荤€规洘绻傞濂稿炊閵娿儱绨ユ繝鐢靛█濞佳囶敄閸涱垳鐭嗛柛鎰靛枟閻撶喖鏌熸导瀛樻锭濠⒀呯帛娣囧﹪顢曢敐鍥╃杽濠殿喖锕ら…宄扮暦閹烘垟鏋庨柟鐑樺灥鐢垶姊绘担渚敯婵炲懏娲熼獮鎴﹀炊瑜忛弳锕傛煟閵忊懚褰掑礃閳ь剙顪冮妶鍡樺暗闁稿鍠栭、娆撳幢濞戞瑢鎷洪柣鐘充航閸斿苯鈻嶉幇鐗堢厵闁告垯鍊栫€氾拷