黄色网页视频 I 影音先锋日日狠狠久久 I 秋霞午夜毛片 I 秋霞一二三区 I 国产成人片无码视频 I 国产 精品 自在自线 I av免费观看网站 I 日本精品久久久久中文字幕5 I 91看视频 I 看全色黄大色黄女片18 I 精品不卡一区 I 亚洲最新精品 I 欧美 激情 在线 I 人妻少妇精品久久 I 国产99视频精品免费专区 I 欧美影院 I 欧美精品在欧美一区二区少妇 I av大片网站 I 国产精品黄色片 I 888久久 I 狠狠干最新 I 看看黄色一级片 I 黄色精品久久 I 三级av在线 I 69色综合 I 国产日韩欧美91 I 亚洲精品偷拍 I 激情小说亚洲图片 I 久久国产视频精品 I 国产综合精品一区二区三区 I 色婷婷国产 I 最新成人av在线 I 国产私拍精品 I 日韩成人影音 I 日日夜夜天天综合

java解惑你知多少(七)

系統(tǒng) 2210 0

應(yīng)用

47.?不可變的引用類(lèi)型

Java代碼?? 收藏代碼
  1. BigInteger?total?=?BigInteger.ZERO;??
  2. total.add( new ?BigInteger( "1" ));??
  3. total.add( new ?BigInteger( "10" ));??
  4. System.out.println(total); //0 ??

上面程序的結(jié)果為11嗎?答案是0。

?

BigInteger實(shí)例是不可變的。String、BigDecimal以及包裝類(lèi)型:Integer、Long、Short、Byte、Character、Boolean、Float和Double也是如此。對(duì)這些類(lèi)型的操作將返回新的實(shí)例。

?

不可變類(lèi)型更容易設(shè)計(jì)、實(shí)現(xiàn)與作用;它們出錯(cuò)的可能性更小,并且更加安全。

?

本程序修改如下:

Java代碼?? 收藏代碼
  1. BigInteger?total?=?BigInteger.ZERO;??
  2. total=total.add( new ?BigInteger( "1" ));??
  3. total=total.add( new ?BigInteger( "10" ));??
  4. System.out.println(total); //11 ??

?

48.?請(qǐng)同時(shí)重寫(xiě)equals()與hashCode()

Java代碼?? 收藏代碼
  1. class ?T?{??
  2. ? private ?String?str;??
  3. ??
  4. ?T(String?str)?{??
  5. ?? this .str?=?str;??
  6. ?}??
  7. ??
  8. ? public ? boolean ?equals(Object?obj)?{??
  9. ?? if (!(obj? instanceof ?T)){??
  10. ??? return ? false ;??
  11. ??}??
  12. ??T?t?=?(T)obj;??
  13. ?? return ?t.equals( this .str);??
  14. ?}??
  15. ??
  16. ? public ? static ? void ?main(String[]?args)?{??
  17. ??Set?set?=? new ?HashSet();??
  18. ??set.add( new ?T( "str" ));??
  19. ??System.out.println(set.contains( new ?T( "str" ))); //false ??
  20. ?}??
  21. }??

上面的程序不會(huì)打印true,而是false,為什么?

?

hashCode約定要求相等的對(duì)象要具有相同的散列碼。

?

無(wú)論何時(shí),只要你重寫(xiě)了equals方法,你就必須同時(shí)重寫(xiě)hashCode方法。

?

如果將自定的類(lèi)型對(duì)象放入HashSet、HashMap、Hashtable、LinkedHashSet、LinkedHashMap這此散列集合時(shí),一定需要重寫(xiě)equals與hashCode方法,這樣在放入進(jìn)去之后還能查找出來(lái)。如果放入其他非散列類(lèi)型的集合時(shí),其實(shí)只需要

重寫(xiě)equals就可以了。

?

本程序解決辦法重寫(xiě)hashCode()方法:

Java代碼?? 收藏代碼
  1. public ? int ?hashCode()?{??
  2. ? return ? 37 ?*? this .str.hashCode();??
  3. }??

?
49.?日期設(shè)置

Java代碼?? 收藏代碼
  1. Calendar?c?=?Calendar.getInstance();??
  2. c.set( 2010 ,? 12 ,? 31 ); //?月是從0開(kāi)始的,11其實(shí)表示12月 ??
  3. System.out.println(c.get(Calendar.YEAR)?+? "?" ?+?c.get(Calendar.MONTH));??
  4. c?=?Calendar.getInstance();??
  5. c.set( 2010 ,? 11 ,? 31 );??
  6. System.out.println(c.get(Calendar.YEAR)?+? "?" ?+?c.get(Calendar.MONTH));??

本程序較簡(jiǎn)單,只需注意月是從0開(kāi)始的就可以了,如果你設(shè)置月為12,則會(huì)自動(dòng)轉(zhuǎn)換為下一年。


50.?IdentityHashMap


?

Java代碼?? 收藏代碼
  1. class ?T?{??
  2. ? private ?String?str;??
  3. ??
  4. ?T(String?str)?{??
  5. ?? this .str?=?str;??
  6. ?}??
  7. ??
  8. ? public ? int ?hashCode()?{??
  9. ?? return ? 37 ?*? this .str.hashCode();??
  10. ?}??
  11. ??
  12. ? public ? boolean ?equals(Object?obj)?{??
  13. ?? return ? this .str.equals(((T)?obj).str);??
  14. ?}??
  15. ??
  16. ? public ? static ? void ?put(Map?m)?{??
  17. ??m.put( "str" ,? "1" );??
  18. ?? /* ?
  19. ???*?由于上面程序?qū)?"str"?放入了字符串常量池, ?
  20. ???*?所以str是同一個(gè)對(duì)象,不管是什么樣類(lèi)型的 ?
  21. ???*?Map,即使使用IdentityHashMap都只放入一次 ?
  22. ???*/ ??
  23. ??m.put( "str" ,? "2" );??
  24. ??m.put( new ?T( "str" ),? "3" );??
  25. ??m.put( new ?T( "str" ),? "4" );??
  26. ?}??
  27. ??
  28. ? public ? static ? void ?main(String[]?args)?{??
  29. ??Map?m?=? new ?HashMap();??
  30. ??put(m);??
  31. ??System.out.println(m.size()); //?2 ??
  32. ?? //IdentityHashMap比較時(shí)使用==替換equals()方法 ??
  33. ??m?=? new ?IdentityHashMap();??
  34. ??put(m);??
  35. ??System.out.println(m.size()); //?3 ??
  36. ?}??
  37. }??

?

51.?靜態(tài)導(dǎo)入的優(yōu)先權(quán)

Java代碼?? 收藏代碼
  1. import ? static ?java.util.Arrays.toString;??
  2. import ?java.util.Arrays;??
  3. public ? class ?T?{??
  4. ? public ? static ? void ?main(String[]?args)?{??
  5. ??prt( 1 ,? 2 ,? 3 );??
  6. ?}??
  7. ? static ? void ?prt(Object...?args)?{??
  8. ?? //?自身繼承至Object類(lèi)的toString的優(yōu)先級(jí)高于靜態(tài)導(dǎo)入的方法 ??
  9. ?? //!!?System.out.println(toString(args));//不能編譯 ??
  10. ??System.out.println(Arrays.toString(args));??
  11. ?}??
  12. }??

本身就屬于某個(gè)范圍的成員在該范圍內(nèi)與靜態(tài)導(dǎo)入相比具有優(yōu)先權(quán)。


52.?PrintStream對(duì)輸出結(jié)果的緩沖

Java代碼?? 收藏代碼
  1. public ? static ? void ?main(String[]?args)?{??
  2. ?String?str?=? "Hello?World" ;??
  3. ? for ?( int ?i?=? 0 ;?i?<?str.length();?i++)?{??
  4. ??System.out.write(str.charAt(i));??
  5. ?}??
  6. }??

上面的程序沒(méi)有輸出結(jié)果。

?

這里的問(wèn)題在于System.out是帶有緩沖的。輸出的結(jié)果被寫(xiě)入了System.out的緩沖區(qū),但是緩沖區(qū)從來(lái)都沒(méi)有被刷新。大多數(shù)人認(rèn)為,當(dāng)有輸出產(chǎn)生的時(shí)候System.out和System.err會(huì)自動(dòng)地進(jìn)制刷新,但這并不完全正確,這兩個(gè)流都屬于PrintStream類(lèi)型,請(qǐng)看API DOC描述:一個(gè)PrintStream被創(chuàng)建為自動(dòng)刷新,這意味著當(dāng)一個(gè)字節(jié)數(shù)組(byte[])被寫(xiě)入、或者某個(gè)println方法被調(diào)用、或者一個(gè)換行字符或字節(jié)('\n')被寫(xiě)入之后,PrintStream類(lèi)型的flush方法就會(huì)被自動(dòng)調(diào)用。

?

令人奇怪的是,如果這個(gè)程序用print(char)去替代write(int),它就會(huì)刷新System.out并輸出結(jié)果,這種行為與print(char)的文檔是矛盾的,因?yàn)槠湮臋n敘述道:“打印一個(gè)字符,這個(gè)字符將根據(jù)平臺(tái)缺省的字符編碼方式翻譯成一個(gè)或多個(gè)字節(jié),并且這些字節(jié)將完全按照write(int)方法的方式輸出。”,但這里沒(méi)有換行符卻也自動(dòng)的刷新了。

?

類(lèi)似的,如果程序改用print(String),它也會(huì)對(duì)流進(jìn)行刷新。所以調(diào)用print方法也是會(huì)自動(dòng)刷新的。

?

53.?調(diào)用操作系統(tǒng)命令時(shí)被阻塞問(wèn)題

Java代碼?? 收藏代碼
  1. public ? static ? void ?main(String[]?args)? throws ?IOException,??
  2. ??InterruptedException?{??
  3. ?String?command?=? "java?ProcessTest?exc" ;??
  4. ? if ?(args.length?!=? 0 )?{??
  5. ?? for ?( int ?i?=? 0 ;?i?<? 200 ;?i++)?{??
  6. ???System.out.println(command);??
  7. ???System.err.println(command);??
  8. ??}??
  9. ?}? else ?{??
  10. ??Process?process?=?Runtime.getRuntime().exec(command);????
  11. ?? int ?exitValue?=?process.waitFor();??
  12. ??System.out.println( "exit?value?=?" ?+?exitValue);??
  13. ?}??
  14. }??

執(zhí)行java ProcessTest發(fā)現(xiàn)程序阻塞。

?

Process文檔描述:由于某些本地平臺(tái)只提供有限大小的緩沖,所以如果不能迅速地讀取子進(jìn)程的輸出流,就有可能會(huì)導(dǎo)致子進(jìn)程的阻塞,甚至是死鎖。這恰好就是這里所發(fā)生的事情:沒(méi)有足夠的緩沖空間來(lái)保存這些輸出結(jié)果。為了結(jié)子進(jìn)程(Process線(xiàn)程),父進(jìn)程(Main線(xiàn)程)必須排空它的輸出流(標(biāo)準(zhǔn)流與錯(cuò)誤流都需要排空),即要去緩存中讀取結(jié)果:

Java代碼?? 收藏代碼
  1. static ? void ?readResult( final ?InputStream?is)?{??
  2. ? new ?Thread( new ?Runnable()?{??
  3. ?? public ? void ?run()?{??
  4. ??? try ?{??
  5. ???? //?排空緩存內(nèi)容 ??
  6. ???? while ?(is.read()?>=? 0 );??
  7. ???}? catch ?(IOException?e)?{??
  8. ????e.printStackTrace();??
  9. ???}??
  10. ??}??
  11. ?}).start();??
  12. }??

?

然后在process.waitFor()之前加上

Java代碼?? 收藏代碼
  1. readResult(process.getErrorStream());??
  2. readResult(process.getInputStream());??

即可輸出exit value = 0。

?

另外,只能根據(jù)process.waitFor返回的結(jié)果來(lái)判斷操作系統(tǒng)命令執(zhí)行是否成功(成功:0,失敗:1),我們不能根據(jù)

錯(cuò)誤流中是否有內(nèi)容來(lái)判斷是否執(zhí)行成功。


54.?實(shí)現(xiàn)Serializable的單例問(wèn)題

Java代碼?? 收藏代碼
  1. class ?Dog? implements ?Serializable{??
  2. ? public ? static ? final ?Dog?INSTANCE?=? new ?Dog();??
  3. ? private ?Dog(){}??
  4. }??

?上面能控制只生成一個(gè)單實(shí)例嗎?

?

如果對(duì)實(shí)現(xiàn)了Serializable的對(duì)象進(jìn)行序列化后,再反序列化,內(nèi)中會(huì)不只一個(gè)實(shí)例了,因?yàn)榉葱蛄谢瘯r(shí)會(huì)重新生成一個(gè)對(duì)象。

?

既然INSTANCE為靜態(tài)域,那序列化時(shí)返回的對(duì)象如果也是INSTANCE就可以解決問(wèn)題了,而打開(kāi)API我們發(fā)現(xiàn)Serializable接口確實(shí)有這樣兩個(gè)特殊的方法描述:
??將對(duì)象寫(xiě)入流時(shí)需要指定要使用的替代對(duì)象的可序列化類(lèi),應(yīng)使用準(zhǔn)確的簽名來(lái)實(shí)現(xiàn)此特殊方法:
ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
此 writeReplace 方法將由序列化調(diào)用,前提是如果此方法存在,而且它可以通過(guò)被序列化對(duì)象的類(lèi)中定義的一個(gè)方法訪問(wèn)。因此,該方法可以擁有私有 (private)、受保護(hù)的 (protected) 和包私有 (package-private) 訪問(wèn)。子類(lèi)對(duì)此方法的訪問(wèn)遵循 java 訪問(wèn)規(guī)則。?
??在從流中讀取類(lèi)的一個(gè)實(shí)例時(shí)需要指定替代的類(lèi)應(yīng)使用的準(zhǔn)確簽名來(lái)實(shí)現(xiàn)此特殊方法:
ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
此 readResolve 方法遵循與 writeReplace 相同的調(diào)用規(guī)則和訪問(wèn)規(guī)則。

?

上述兩個(gè)方法的只要出現(xiàn),就會(huì)履蓋以下兩個(gè)方法(這兩個(gè)方法本質(zhì)的意義就是用來(lái)替換序列與反序列的對(duì)象),雖然會(huì)執(zhí)行它們,但最后得到的結(jié)果卻是writeReplace、readResolve兩個(gè)方法寫(xiě)入或讀出的對(duì)象:
??private void writeObject(java.io.ObjectOutputStream out) throws IOException
??private void readObject(java.io.ObjectInputStream in)throws IOException, ClassNotFoundException;

?

另外,writeObject與readObject需成對(duì)實(shí)現(xiàn),而writeReplace與readResolve則不需要成對(duì)出現(xiàn),一般單獨(dú)使用。如果同時(shí)出現(xiàn)這四個(gè)方法,最后寫(xiě)入與讀出的結(jié)果以writeReplace和readResolve方法的結(jié)果為準(zhǔn)。

?

所以下要解決真真單實(shí)例問(wèn)題,我們?nèi)缦滦拚?

Java代碼?? 收藏代碼
  1. class ?Dog? implements ?Serializable?{??
  2. ? public ? static ? final ?Dog?INSTANCE?=? new ?Dog();??
  3. ? private ?Dog()?{}??
  4. ? private ?Object?readResolve()?{??
  5. ?? return ?INSTANCE;??
  6. ?}??
  7. }??
  8. ??
  9. public ? class ?SerialDog?{??
  10. ? public ? static ? void ?main(String[]?args)? throws ?IOException,??
  11. ???ClassNotFoundException?{??
  12. ??ByteArrayOutputStream?bos?=? new ?ByteArrayOutputStream();??
  13. ?? new ?ObjectOutputStream(bos).writeObject(Dog.INSTANCE);??
  14. ??ByteArrayInputStream?bin?=? new ?ByteArrayInputStream(bos.toByteArray());??
  15. ??Dog?dog?=?(Dog)? new ?ObjectInputStream(bin).readObject();??
  16. ??System.out.println(dog?==?Dog.INSTANCE); //true ??
  17. ?}??
  18. }??

一個(gè)實(shí)現(xiàn)了Serializable的單例類(lèi),必須有一個(gè)readResolve方法,用以返回它的唯一實(shí)例。


55.?thread. isInterrupted()與Thread.interrupted()

Java代碼?? 收藏代碼
  1. public ? class ?SelfInerruption?{??
  2. ? public ? static ? void ?main(String[]?args)?{??
  3. ??Thread.currentThread().interrupt();??
  4. ?? if ?(Thread.interrupted())?{??
  5. ??? //?Interruped:false ??
  6. ???System.out.println( "Interruped:" ?+?Thread.interrupted());??
  7. ??}? else ?{??
  8. ???System.out.println( "Not?interruped:" ?+?Thread.interrupted());??
  9. ??}??
  10. ?}??
  11. }??

上面結(jié)果走的是第一個(gè)分支,但結(jié)果卻不是Interruped:true?

?

Thread.interrupted()為T(mén)hread的靜態(tài)方法,調(diào)用它首先會(huì)返回當(dāng)前線(xiàn)程的中斷狀態(tài)(如果當(dāng)前線(xiàn)程上調(diào)用了interrupt()方法,則返回true,否則為false),然后再清除當(dāng)前線(xiàn)程的中斷狀態(tài),即將中斷狀態(tài)設(shè)置為false。換句話(huà)說(shuō),如果連續(xù)兩次調(diào)用該方法,則第二次調(diào)用將返回 false。

?

而isInterrupted()方法為實(shí)例方法,測(cè)試線(xiàn)程是否已經(jīng)中斷,并不會(huì)清除當(dāng)前線(xiàn)程中斷狀態(tài)。

?

所以這里應(yīng)該使用isInterrupted()實(shí)例方法,就可以修復(fù)該問(wèn)題。

?

java解惑你知多少(七)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論