版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
每天在寫程序,其實(shí)里面有一些細(xì)節(jié)大家可能沒怎么注意,這不,有人總結(jié)了一個我們編程中常見的問題。雖然一般沒有什么大問題,但是最好別這樣做。另外這里提到的很多問題其實(shí)可以通過來幫我們進(jìn)行檢查出來。字符串連接誤用錯誤的寫法:Strings="";for(Personp:persons){s+=","+p.getName();}s=s.substring(2);//removefirstcomma正確的寫法:StringBuildersb=newStringBuilder(persons.size()*16);//wellestimatedbufferfor(Personp:persons){if(sb.length()>0)sb.append(",");sb.append(p.getName);}錯誤的使用錯誤的寫法:StringBuffersb=newStringBuffer();sb.append("Name:");sb.append(name+'\n');sb.append("!");...Strings=sb.toString();問題在第三行,比性能要好,另外就是初始化沒有指定導(dǎo)致中間時可能重新調(diào)整內(nèi)部數(shù)組大小。如果是最好用取代,除非有線程安全的要求。還有一種方式就是可以直接連接字符串。缺點(diǎn)就是無法初始化時指定長度。正確的寫法:StringBuildersb=newStringBuilder(100);sb.append("Name:");sb.append(name);sb.append("\n!");Strings=sb.toString();或者這樣寫:Strings="Name:"+name+"\n!";測試字符串相等性錯誤的寫法:if(pareTo("John")==0)...if(name=="John")...if(name.equals("John"))...if("".equals(name))...上面的代碼沒有錯,但是不夠好。不夠簡潔,原義是比較兩個對象是否一樣。另外比較字符是否為空,最好判斷它的長度。正確的寫法:if("John".equals(name))...if(name.length()==0)...if(name.isEmpty())...數(shù)字轉(zhuǎn)換成字符串錯誤的寫法:""+set.size()newInteger(set.size()).toString()正確的寫法:String.valueOf(set.size())利用不可變對象錯誤的寫法:zero=newInteger(0);returnBoolean.valueOf("true");正確的寫法:zero=Integer.valueOf(0);returnBoolean.TRUE;請使用解析器錯誤的寫法:intstart=xml.indexOf("<name>")+"<name>".length();intend=xml.indexOf("</name>");Stringname=xml.substring(start,end);正確的寫法:SAXBuilderbuilder=newSAXBuilder(false);Documentdoc=doc=builder.build(newStringReader(xml));Stringname=doc.getRootElement().getChild("name").getText();請使用組裝錯誤的寫法:Stringname=...Stringattribute=...Stringxml="<root>+"<nameatt=\""+attribute+"\">"+name+"</name>+"</root>";正確的寫法:Elementroot=newElement("root");root.setAttribute("att",attribute);root.setText(name);Documentdoc=newDocumet();doc.setRootElement(root);XmlOutputterout=newXmlOutputter(Format.getPrettyFormat());Stringxml=out.outputString(root);編碼陷阱錯誤的寫法:Stringxml=FileUtils.readTextFile("my.xml");因?yàn)榈木幋a在文件中指定的,而在讀文件的時候必須指定編碼。另外一個問題不能一次就將一個文件用保存,這樣對內(nèi)存會造成不必要的浪費(fèi),正確的做法用來邊讀取邊處理。為了解決編碼的問題最好使用解析器來處理。未指定字符編碼錯誤的寫法:Readerr=newFileReader(file);Writerw=newFileWriter(file);Readerr=newInputStreamReader(inputStream);Writerw=newOutputStreamWriter(outputStream);Strings=newString(byteArray);//byteArrayisabyte[]
byte[]a=string.getBytes();這樣的代碼主要不具有跨平臺可移植性。因?yàn)椴煌钠脚_可能使用的是不同的默認(rèn)字符編碼。正確的寫法:Readerr=newInputStreamReader(newFileInputStream(file),"ISO-8859-1");Writerw=newOutputStreamWriter(newFileOutputStream(file),"ISO-8859-1");Readerr=newInputStreamReader(inputStream,"UTF-8");Writerw=newOutputStreamWriter(outputStream,"UTF-8");Strings=newString(byteArray,"ASCII");byte[]a=string.getBytes("ASCII");未對數(shù)據(jù)流進(jìn)行緩存錯誤的寫法:InputStreamin=newFileInputStream(file);intb;while((b=in.read())!=-1){...}上面的代碼是一個一個的讀取,導(dǎo)致頻繁的本地文件系統(tǒng)訪問,非常低效,因?yàn)檎{(diào)用本地方法是非常耗時的。最好用包裝一下。曾經(jīng)做過一個
因?yàn)檎{(diào)用本地方法是非常耗時的。最好用包裝一下。曾經(jīng)做過一個測試,從下讀取,大概花了,而用包裝之后只測試,從下讀取,大概花了,而用包裝之后只需要,性能提高了這個也適用于操作以及操作。正確的寫法:InputStreamin=newBufferedInputStream(newFileInputStream(file));無限使用內(nèi)存錯誤的寫法:byte[]pdf=toPdf(file);這里有一個前提,就是文件大〃\不能講的撐爆。否則就等著吧,尤其是在高并發(fā)的服務(wù)器端代碼。最好的做法是采用的方式邊讀取邊存儲本地文件或。正確的寫法:Filepdf=toPdf(file);另外,對于服務(wù)器端代碼來說,為了系統(tǒng)的安全,至少需要對文件的大小進(jìn)行限制。不指定超時時間錯誤的代碼:Socketsocket=...socket.connect(remote);InputStreamin=socket.getInputStream();inti=in.read();這種情況在工作中已經(jīng)碰到不止一次了。個人經(jīng)驗(yàn)一般超時不要超過。這里有一個問題,可以指定超時時間,但是無法指定超時時間。但是可以設(shè)置阻塞時間。正確的寫法:Socketsocket=...socket.connect(remote,20000);//failafter20sInputStreamin=socket.getInputStream();socket.setSoTimeout(15000);inti=in.read();另外,文件的讀取沒法指定超時時間而且操作均涉及到本地方法調(diào)用這個更操作了的控制范圍,在分布式文件系統(tǒng)中,對的操作內(nèi)部實(shí)際上是網(wǎng)絡(luò)調(diào)用。一般情況下操作的操作都可以認(rèn)為已經(jīng)超時了。為了解決這些問題,一般采用緩存和異步/消息隊(duì)列處理。頻繁使用計時器錯誤代碼:for(...){longt=System.currentTimeMillis();longt=System.nanoTime();Dated=newDate();Calendarc=newGregorianCalendar();
每次都會涉及一次本地調(diào)用來獲取當(dāng)前時間盡管這個本地調(diào)每次都會涉及一次本地調(diào)用來獲取當(dāng)前時間盡管這個本地調(diào)用相對其他本地方法調(diào)用要快)。如果對時間不是特別敏感,這里使用了方法來新建一個實(shí)例。這樣相對直接要高效一些。正確的寫法:Dated=newDate();for(Eentity:entities){entity.doSomething();entity.setUpdated((Date)d.clone());}如果循環(huán)操作耗時較長超過幾,那么可以采用下面的方法,立即創(chuàng)建一個,然后定期根據(jù)當(dāng)前時間更新時間戳,在我的系統(tǒng)上比直接一個時間對象快倍:privatevolatilelongtime;Timertimer=newTimer(true);try{time=System.currentTimeMillis();timer.scheduleAtFixedRate(newTimerTask(){publicvoidrun(){time=System.currentTimeMillis();}},0L,10L);//granularity10msfor(Eentity:entities){entity.doSomething();entity.setUpdated(newDate(time));}}finally{timer.cancel();}捕獲所有的異常錯誤的寫法:Queryq=...Personp;try{p=(Person)q.getSingleResult();}catch(Exceptione){p=null;}這是的一個查詢操作,可能出現(xiàn)異常的原因是:結(jié)果不唯一;沒有結(jié)果;數(shù)據(jù)庫無法訪問,而捕獲所有的異常,設(shè)置為將掩蓋各種異常情況。正確的寫法:Queryq=...Personp;try{p=(Person)q.getSingleResult();}catch(NoResultExceptione){p=null;}忽略所有異常錯誤的寫法:try{doStuff();}catch(Exceptione){log.fatal("Couldnotdostuff");}doMoreStuff();這個代碼有兩個問題,一個是沒有告訴調(diào)用者,系統(tǒng)調(diào)用出錯了.第二個是日志沒有出錯原因,很難跟蹤定位問題。正確的寫法:try{doStuff();}catch(Exceptione){thrownewMyRuntimeException("Couldnotdostuffbecause:"+e.getMessage,e);}}catch(IOExceptione){}}catch(NamingExceptione){重復(fù)包裝錯誤的寫法:try{doStuff();}catch(Exceptione){thrownewRuntimeException(e);}正確的寫法:try{doStuff();}catch(RuntimeExceptione){throwe;}catch(Exceptione){thrownewRuntimeException(e.getMessage(),e);}try{doStuff();}catch(IOExceptione){thrownewRuntimeException(e.getMessage(),e);thrownewRuntimeException(e.getMessage(),e);}不正確的傳播異常錯誤的寫法:try{}catch(ParseExceptione){thrownewRuntimeException();thrownewRuntimeException(e.toString());thrownewRuntimeException(e.getMessage());thrownewRuntimeException(e);}主要是沒有正確的將內(nèi)部的錯誤信息傳遞給調(diào)用者.第一個完全丟掉了內(nèi)部錯誤信息,第二個錯誤信息依賴方法如果沒有包含最終的嵌套錯誤信息也會出現(xiàn)丟失而且可讀性差.第三個稍微好一些,第四個跟第二個一樣。正確的寫法:try{}catch(ParseExceptione){thrownewRuntimeException(e.getMessage(),e);}用日志記錄異常錯誤的寫法:try{...}catch(ExceptionAe){log.error(e.getMessage(),e);throwe;}catch(ExceptionBe){log.error(e.getMessage(),e);throwe;}一般情況下在日志中記錄異常是不必要的,除非調(diào)用方?jīng)]有記錄日志。異常處理不徹底錯誤的寫法:try{is=newFileInputStream(inFile);os=newFileOutputStream(outFile);}finally{try{is.close();os.close();/*wecan'tdoanything*/}}可能失敗導(dǎo)致沒有正確的寫法:try{is=newFileInputStream(inFile);os=newFileOutputStream(outFile);}finally{try{if(is!=null)is.close();}catch(IOExceptione){/*wecan'tdoanything*/}try{if(os!=null)os.close();}catch(IOExceptione){/*wecan'tdoanything*/}}捕獲不可能出現(xiàn)的異常錯誤的寫法:try{...doriskystuff...}catch(SomeExceptione){//neverhappens...dosomemore...正確的寫法:try{...doriskystuff...}catch(SomeExceptione){//neverhappenshopefullypassinthrownewIllegalStateException(e.getMessage(),e);//crashearly,gallinformationpassin}...dosomemore...的誤用錯誤的寫法:publicclassAimplementsSerializable{privateStringsomeState;privatetransientLoglog=LogFactory.getLog(getClass());publicvoidf(){log.debug("enterf");...}這里的本意是不希望對象被序列化不過這里在反序列化時會因?yàn)槲闯跏蓟瘜?dǎo)致方法拋空指針正確的做法是將定義為靜態(tài)變量或者定位為具備變量。正確的寫法:publicclassAimplementsSerializable{privateStringsomeState;privatestaticfinalLoglog=LogFactory.getLog(A.class);publicvoidf(){log.debug("enterf");...}}publicclassAimplementsSerializable{privateStringsomeState;publicvoidf(){Loglog=LogFactory.getLog(getClass());log.debug("enterf");...}}不必要的初始化錯誤的寫法:publicclassB{privateintcount=0;privateStringname=null;privatebooleanimportant=false;}這里的變量會在初始化時使用默認(rèn)值因此上面的寫法有些多此一舉。正確的寫法:publicclassB{privateintcount;privateStringname;privatebooleanimportant;}最好用靜態(tài)定義變量privatestaticfinalLoglog=LogFactory.getLog(MyClass.class);這樣做的好處有三:可以保證線程安全靜態(tài)或非靜態(tài)代碼都可用不會影響對象序列化選擇錯誤的類加載器錯誤的代碼:Classclazz=Class.forName(name);Classclazz=getClass().getClassLoader().loadClass(name);這里本意是希望用當(dāng)前類來加載希望的對象但是這里的可能拋出異常特別在一些受管理的環(huán)境中比如應(yīng)用服務(wù)器容器環(huán)境中最好的做法是使用當(dāng)前應(yīng)用上下文的類加載器來加載。正確的寫法:ClassLoadercl=Thread.currentThread().getContextClassLoader();if(cl==null)cl=MyClass.class.getClassLoader();//fallbackClassclazz=cl.loadClass(name);反射使用不當(dāng)錯誤的寫法:ClassbeanClass=...if(beanClass.newInstance()instanceofTestBean)...這里的本意是檢查是否是或是其子類但是創(chuàng)建一個類實(shí)例可能沒那么簡單,首先實(shí)例化一個對象會帶來一定的消耗,另外有可能類沒有定義默認(rèn)構(gòu)造函數(shù).正確的做法是用方法。正確的寫法:ClassbeanClass=...if(TestBean.class.isAssignableFrom(beanClass))不必要的同步錯誤的寫法:Collectionl=newVector();for(...){l.add(object);}是同步版本。正確的寫法:Collectionl=newArrayList();for(...){l.add(object);}錯誤的選擇類型根據(jù)下面的表格數(shù)據(jù)來進(jìn)行選擇陷阱錯誤的寫法:Mapmap=newHashMap(collection.size());for(Objecto:collection){map.put(o.key,o.value);}這里可以參考的的實(shí)現(xiàn)用戶的本意是希望給設(shè)置初始值避免擴(kuò)容的開銷但是沒有考慮當(dāng)添加的元素數(shù)量達(dá)到容量的日寸將出現(xiàn)。正確的寫法:Mapmap=newHashMap(1+(int)(collection.size()/0.75));對和了解不夠這里主要需要了解和的內(nèi)部實(shí)現(xiàn)上它們都使用包裝來封裝內(nèi)部除了要保存的引用還需要保存桶中的應(yīng)用因此對內(nèi)存會有不小的開銷而內(nèi)部實(shí)現(xiàn)其實(shí)就是一個有時候可以作為一個不錯的替代方案它在內(nèi)存使用上更有效沒有用封裝內(nèi)部采用不過需要小心使用它的實(shí)現(xiàn)違背了接口的定義有時候也可以用來替換這一切的根源都是由于內(nèi)部沒有提供一套高效的和實(shí)現(xiàn)。}}對的誤用建議下列場景用來替代長度固定,比如一周中的每一天對頻繁的遍歷,比如超過次需要對數(shù)字進(jìn)行包裝(主要沒有提供基本類型的需要對數(shù)字進(jìn)行包裝(主要沒有提供基本類型的比如下面的代碼。錯誤的寫法:List<Integer>codes=newArrayList<Integer>();codes.add(Integer.valueOf(10));codes.add(Integer.valueOf(20));codes.add(Integer.valueOf(30));codes.add(Integer.valueOf(40));正確的寫法:int[]codes={10,20,30,40};錯誤的寫法:(tr//horriblyslowandamemorywasteriflhasafewthousandelementsyityourself!)(trList<Mergeable>l=...;for(inti=0;i<l.size()-1;i++){Mergeableone=l.get(i);Iterator<Mergeable>j=l.iterator(i+1);//memoryallocation!while(j.hasNext()){Mergeableother=l.next();if(one.canMergeWith(other)){one.merge(other);other.remove();}}}正確的寫法://quitefastandnomemoryallocationMergeable[]l=...;for(inti=0;i<l.length-1;i++){Mergeableone=l[i];for(intj=i+1;j<l.length;j++){Mergeableother=l[j];if(one.canMergeWith(other)){one.merge(other);l[j]=null;}}
實(shí)際上也意識到這一點(diǎn)因此在中實(shí)際上也意識到這一點(diǎn)因此在中就是將一個拷貝到一個數(shù)組中然后調(diào)用方法來執(zhí)行排序。用數(shù)組來描述一個結(jié)構(gòu)錯誤用法:/***@returns[1]:Location,[2]:Customer,[3]:Incident*/Object[]getDetails(intid){...這里用數(shù)組+文檔的方式來描述一個方法的返回值.雖然很簡單,但是很容易誤用,正確的做法應(yīng)該是定義個類。正確的寫法:DetailsgetDetails(intid){...}privateclassDetails{publicLocationlocation;publicCustomercustomer;publicIncidentincident;}對方法過度限制錯誤用法:publicvoidnotify(Personp){sendMail(p.getName(),p.getFirstName(),p.getEmail());}classPhoneBook{Stringlookup(StringemployeeId){Employeeemp=...returnemp.getPhone();}}第一個例子是對方法參數(shù)做了過多的限制,第二個例子對方法的返回值做了太多的限制。正確的寫法:publicvoidnotify(Personp){...sendMail(p);...}classEmployeeDirectory{Employeelookup(StringemployeeId){Employeeemp=...returnemp;}}}}對的方法畫蛇添足錯誤的寫法:privateStringname;publicvoidsetName(Stringname){=name.trim();}publicvoidStringgetName(){;}有時候我們很討厭字符串首尾出現(xiàn)空格所以在方法中進(jìn)行了處理但是這樣做的結(jié)果帶來的副作用會使方法的返回值和方法不一致如果只是將當(dāng)做一個數(shù)據(jù)容器那么最好不要包含任何業(yè)務(wù)邏輯而將業(yè)務(wù)邏輯放到專門的業(yè)務(wù)層或者控制層中處理。正確的做法:person.setName(textInput.getText().trim());日歷對象誤用錯誤的寫法:Calendarcal=newGregorianCalender(TimeZone.getTimeZone("Europe/Zurichcal.setTime(date);cal.add(Calendar.HOUR_OF_DAY,8);date=cal.getTime();這里主要是對和不了解導(dǎo)致而在一個時間上增加小時跟沒有任何關(guān)系所以沒有必要使用直接用對象即可而如果是增加天數(shù)的話則需要使用因?yàn)椴捎貌煌臅r令制可能一天的小時數(shù)是不同的比如有些是或者個小時正確的寫法:date=newDate(date.getTime()+8L*3600L*1000L);//add8hrs的誤用錯誤的寫法:Calendarcal=newGregorianCalendar();cal.setTime(date);cal.set(Calendar.HOUR_OF_DAY,0);cal.set(Calendar.MINUTE,0);cal.set(Calendar.SECOND,0);DatestartOfDay=cal.getTime();這里有兩個錯誤一個是沒有沒有將毫秒歸零不過最大的錯誤是沒有指定不過一般的桌面應(yīng)用沒有問題,但是如果是服務(wù)器端應(yīng)用則會有一些問題,比如同一時刻在上海和倫敦就不一樣,因此需要指定的正確的寫法:Calendarcal=newGregorianCalendar(user.getTimeZone());cal.setTime(date);cal.set(Calendar.HOUR_OF_DAY,0);cal.set(Calendar.MINUTE,0);cal.set(Calendar.SECOND,0);cal.set(Calendar.MILLISECOND,0);DatestartOfDay=cal.getTime();時區(qū)調(diào)整的誤用錯誤的寫法:publicstaticDateconvertTz(Datedate,TimeZonetz){Calendarcal=Calendar.getInstance();cal.setTimeZone(TimeZone.getTimeZone("UTC"));cal.setTime(date);cal.setTimeZone(tz);returncal.getTime();}這個方法實(shí)際上沒有改變時間,輸入和輸出是一樣的.關(guān)于時間的問題可以參考這篇文章:這里主要的問題是對象并不包含信息它總是使用世界統(tǒng)一時間而調(diào)用的方法會自動在當(dāng)前時區(qū)和之間做轉(zhuǎn)換。的誤用錯誤的寫法:Calendarc=Calendar.getInstance();c.set(2009,Calendar.JANUARY,15);eti來選擇一個實(shí)現(xiàn)不同實(shí)現(xiàn)的年是不同的比如有些實(shí)現(xiàn)就沒有月份。正確的寫法:Calendarc=newGregorianCalendar(timeZone);c.set(2009,Calendar.JANUARY,15);的誤用錯誤的寫法:account.changePassword(oldPass,newPass);Datelastmod=account.getLastModified();lastmod.setTime(System.currentTimeMillis());在更新密碼之后,修改一下最后更新時間,這里的用法沒有錯,但是有更好的做法:直接傳對象因?yàn)槭遣豢勺兊娜绻铝说闹祵?shí)際上是生成一個新的實(shí)例這樣其他地方用到的實(shí)際上不在是原來的對象這樣可能出現(xiàn)不可預(yù)知的異常當(dāng)然這里又涉及到另外一個設(shè)計的問題對外暴露實(shí)例本身就是不好的做法一般的做法是在方法中設(shè)置引用參數(shù)的對象另外一種比較好的做法就是直接保存類型的毫秒數(shù)。正確的做法:account.changePassword(oldPass,newPass);account.setLastModified(newDate());非線程安全誤用錯誤的寫法:publicclassConstants{publicstaticfinalSimpleDateFormatdate=newSimpleDateFormat("dd.MM.yyyy");}不是線程安全的在多線程并行處理的情況下會得到非預(yù)期的值這個錯誤非常普遍如果真要在多線程環(huán)境下公用同一個那么做好做好同步但是這樣會搞得更復(fù)雜還不如直接一個實(shí)在。使用全局參數(shù)配置常量類/接口publicinterfaceConstants{Stringversion="1.0";StringdateFormat="dd.MM.yyyy";StringconfigFile=".apprc";intmaxNameLength=32;StringsomeQuery="SELECT*FROM...";}}}}很多應(yīng)用都會定義這樣一個全局常量類或接口,但是為什么這種做法不推薦?因?yàn)檫@些常量之間基本沒有任何關(guān)聯(lián),只是因?yàn)楣貌哦x在一起.但是如果其他組件需要使用這些全局變量則必須對該常量類產(chǎn)生依賴特別是存在和遠(yuǎn)程調(diào)用的場景。比較好的做法是將這些常量定義在組件內(nèi)部.或者局限在一個類庫內(nèi)部。忽略造型溢出錯誤的寫法:publicintgetFileSize(Filef){longl=f.length();return(int)l;}這個方法的本意是不支持傳遞超過的文件最好的做法是對長度進(jìn)行檢查溢出時拋出異常。正確的寫法:publicintgetFileSize(Filef){longl=f.length();if(l>Integer.MAX_VALUE)thrownewIllegalStateException("intoverflow");return(int)l;}另一個溢出是另一個溢出是的對象不對比如下面第一個正確的應(yīng)該是下面的那個。longa=System.currentTimeMillis();longb=a+100;System.out.println((int)b-a);System.out.println((int)(b-a));對和使用操作錯誤的寫法:for(floatf=10f;f!=0;f-=0.1){System.out.println(f);}上面的浮點(diǎn)數(shù)遞減只會無限接近而不會等于這樣會導(dǎo)致上面的進(jìn)入死循環(huán)通常絕不要對和使用操作而采用大于和小于操作如果編譯器能針對這種情況給出警告或者在語言規(guī)范中不支持浮點(diǎn)數(shù)類型的操作就最好了。正確的寫法:for(floatf=10f;f>0;f-=0.1){System.out.println(f);}用浮點(diǎn)數(shù)來保存錯誤的寫法:floattotal=0.0f;for(OrderLineline:lines){total+=line.price*line.count;}doublea=1.14*75;//85.5將表示為85.4999...System.out.println(Math.round(a));//輸出值為85BigDecimald=newBigDecimal(1.14);//造成精度丟失這個也是一個老生常談的錯誤.比如計算100筆訂單,每筆0.元3,最終的計算結(jié)果是如果將類型改為類型得到的結(jié)果將是出現(xiàn)這種情況的原因是,人類和計算的計數(shù)方式不同.人類采用的是十進(jìn)制,而計算機(jī)是二進(jìn)制.二進(jìn)制對于計算機(jī)來說非常好使,但是對于涉及到精確計算的場景就會帶來誤差.比如銀行金融中的應(yīng)用。因此絕不要用浮點(diǎn)類型來保存數(shù)據(jù)采用浮點(diǎn)數(shù)得到的計算結(jié)果是不精確的即使與類型做乘法運(yùn)算也會產(chǎn)生一個不精確的結(jié)果那是因?yàn)樵谟枚M(jìn)制存儲一個浮點(diǎn)數(shù)時已經(jīng)出現(xiàn)了精度丟失最好的做法就是用一個或者固定點(diǎn)數(shù)來表示為了精確這種表示方式需要指定相應(yīng)的精度值.就滿足了上面所說的需求如果在計算的過程中精度的丟失超出了給定的范圍將拋出正確的寫法:BigDecimaltotal=BigDecimal.ZERO;for(OrderLineline:lines){BigDecimalprice=newBigDecimal(line.price);BigDecimalcount=newBigDecimal(line.count);total=total.add(price.multiply(count));//BigDecimalisimmutable!}total=total.setScale(2,RoundingMode.HALF_UP);BigDecimala=(newBigDecimal("1.14")).multiply(newBigDecimal(75));//85.5exacta=a.setScale(0,RoundingMode.HALF_UP);//86System.out.println(a);//correctoutput:86BigDecimala=newBigDecimal("1.14");不使用塊釋放資源錯誤的寫法:publicvoidsave(Filef)throwsIOException{OutputStreamout=newBufferedOutputStream(newFileOutputStream(f));out.write(...);out.close();}publicvoidload(Filef)throwsIOException{InputStreamin=newBufferedInputStream(newFileInputStream(f));in.read(...);in.close();
上面的代碼打開一個文件輸出流,操作系統(tǒng)為其分配一個文件句柄,但是文件句柄是一種非常稀缺的資源必須通過調(diào)用相應(yīng)的方法來被正確的釋放回收而為了保證在異常情況下資源依然能被正確回收,必須將其放在中上面的代碼中使用了況下資源依然能被正確回收,必須將其放在中上面的代碼中使用了將方法時才會將不完全而對于如果將方法時才會將不完全而對于如果包裝成了一個寫入磁盤如果在在的這樣將導(dǎo)致在調(diào)用的時候失敗將導(dǎo)致寫入數(shù)據(jù)操作這里將直接忽略。方法執(zhí)行順利則萬事大吉如果失敗這里有一個潛在在方法內(nèi)部調(diào)用操作的時候如果出現(xiàn)異常將直接忽略因此為了盡量減少數(shù)據(jù)丟失在執(zhí)行之前顯式的調(diào)用操作。下面的代碼有一個小小的瑕疵如果分配成功但是分配失敗這種場景將導(dǎo)致文件句柄未被正確釋放不過這種情況一般不用擔(dān)心因?yàn)榈膶椭覀冏銮謇怼?/codeforyourcookbookpublicvoidsave()throwsIOException{Filef=...OutputStreamout=newBufferedOutputStream(newFileOutputStream(f));try{out.write(...);out.flush();//don'tloseexceptionbyimplicitflushonclose}finally{out.close();}}}}}publicvoidload(Filef)throwsIOException{InputStreamin=newBufferedInputStream(newFileInputStream(f));try{in.read(...);}finally{try{in.close();}catch(IOExceptione){}}}數(shù)據(jù)庫訪問也涉及到類似的情況:CargetCar(DataSourceds,Stringplate)throwsSQLException{Carcar=null;Connectionc=null;PreparedStatements=null;ResultSetrs=null;try{c=ds.getConnection();s=c.prepareStatement("selectmake,colorfromcarswhereplate=?");s.setString(1,plate);rs=s.executeQuery();if(rs.next()){car=newCar();car.make=rs.getString(1);car.color=rs.getString(2);}}finally{TOC\o"1-5"\h\zif(rs!=null)try{rs.close();}catch(SQLExceptione){}if(s!=null)try{s.close();}catch(SQLExceptione){}if(c!=null)try{c.close();}catch(SQLExceptione){}}returncar;}方法誤用錯誤的寫法:publicclassFileBackedCache{privateFilebackingStore;...protectedvoidfinalize()throwsIOException{if(backingStore!=null){backingStore.close();
backingStore=null;}}}這個
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024全年物業(yè)綠化維護(hù)服務(wù)合同
- 2024年大型購物中心商業(yè)管理合同
- 2024vr的產(chǎn)品技術(shù)產(chǎn)品技術(shù)開發(fā)合同范本
- 2024年度八寶山殯儀館鮮花制品質(zhì)量保證與售后服務(wù)合同
- 2024年度大數(shù)據(jù)服務(wù)合同的數(shù)據(jù)安全
- 2024年度35kv變電站施工期間安全培訓(xùn)合同
- 2024填塘渣工程質(zhì)量保障合同
- 2024年度供暖設(shè)備安裝工程合同
- 2024年家長學(xué)校協(xié)作合同
- 2024年廣西體育館大院乒乓球俱樂部會員合同
- 計算機(jī)圖形學(xué)文獻(xiàn)綜述
- QC080000-2017標(biāo)準(zhǔn)講解培訓(xùn)教材
- 鋼板樁支護(hù)工程監(jiān)理實(shí)施細(xì)則
- 中考150個實(shí)詞(供默寫)
- Module 5 外研版英語九(上)模塊主題寫作詳解與訓(xùn)練
- 第二章攪拌摩擦焊
- 內(nèi)分泌科醫(yī)師培養(yǎng)細(xì)則
- 蛋白質(zhì)與酶工程復(fù)習(xí)題 金
- 五金件通用檢驗(yàn)標(biāo)準(zhǔn)
- kummell 病ppt課件
- 小班綜合活動《出生的秘密》
評論
0/150
提交評論