c=newComparator(){publicintcompare(Integeri1,Integeri2){returni1-i2;//升序}};Listl=newArrayList();l.add(newInteger(-2000000000));l.add(newInteger(2000000000));Collec" />

日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

java解惑你知多少(三)

系統(tǒng) 2461 0

17.?不要使用基于減法的比較器

Java代碼 ? ? 收藏代碼
  1. Comparator<Integer>?c?=? new ?Comparator<Integer>()?{??
  2. ? public ? int ?compare(Integer?i1,?Integer?i2)?{??
  3. ?? return ?i1?-?i2; //?升序 ??
  4. ?}??
  5. };??
  6. List<Integer>?l?=? new ?ArrayList<Integer>();??
  7. l.add( new ?Integer(- 2000000000 ));??
  8. l.add( new ?Integer( 2000000000 ));??
  9. Collections.sort(l,?c);??
  10. System.out.println(l); //?[2000000000,?-2000000000] ??

上面程序的比較器是升序,結(jié)果卻不是這樣,比較時(shí)出現(xiàn)了什么問題?

?

先看看下面程序片斷:

Java代碼 ? ? 收藏代碼
  1. int ?x?=?- 2000000000 ;??
  2. int ?y?=? 2000000000 ;??
  3. /* ?
  4. ?*?-2000000000?即?-(01110111001101011001010000000000) ?
  5. ?*?的補(bǔ)碼為:????????????????10001000110010100110110000000000 ?
  6. ?*? ?
  7. ?*?計(jì)算過程使用豎式表示: ?
  8. ?*?10001000110010100110110000000000 ?
  9. ?*?10001000110010100110110000000000 ?
  10. ?*?-------------------------------- ?
  11. ?*?00010001100101001101100000000000 ?
  12. ?*? ?
  13. ?*?計(jì)算結(jié)果溢出,結(jié)果為294967296 ?
  14. ?*/ ??
  15. System.out.println(x?-?y); //?294967296 ??

所以不要使用減法的比較器,除非能確保要比較的數(shù)值之間的距離永遠(yuǎn)不會(huì)大于Intger. MAX_VALUE。

?

基于整型的比較器的實(shí)現(xiàn)一般使用如下的方式來比較:

Java代碼 ? ? 收藏代碼
  1. public ? int ?compare(Integer?i1,?Integer?i2)?{??
  2. ? return ?(i1?<?i2???- 1 ?:?(i1?==?i2??? 0 ?:? 1 ));??
  3. }??

?
18.? int i=-2147483648與int i=-(2147483648)?

Java代碼 ? ? 收藏代碼
  1. int ?i=-( 2147483648 );??

編譯通不過!為什么

?

int字面常量2147483638只能作為一元負(fù)操作符的操作數(shù)來使用。

?

類似的還有最大long:

Java代碼 ? ? 收藏代碼
  1. long ?i=–(9223372036854775808L);??

?
字符串

19.?char類型相加

Java代碼 ? ? 收藏代碼
  1. System.out.println( 'a' ?+? 'A' ); //162 ??

上面的結(jié)果不是 aA ,而是 162。


當(dāng)且僅當(dāng)+操作符的操作數(shù)中至少有一個(gè)是String類型時(shí),才會(huì)執(zhí)行字符串連接操作;否則,執(zhí)行加法。如果要連接的

數(shù)值沒有一個(gè)是字符串類型的,那么你可以有幾種選擇:預(yù)置一個(gè)空字符串("" + 'a' + 'A');將第一個(gè)數(shù)值用

String.valueOf()顯示地轉(zhuǎn)換成一個(gè)字符串(String.valueOf('a') + 'A');使用一個(gè)字符串緩沖區(qū)(sb.append

('a');sb.append('A'););或者如果使用的是JDK5.0,可以用printf(System.out.printf("%c%c",'a','A'));


20.?程序中的Unicode轉(zhuǎn)義字符

Java代碼 ? ? 收藏代碼
  1. //\u0022是雙引號(hào)的Unicode編碼表示 ??
  2. System.out.println( "a\u0022.length()?+?\u0022b" .length()); //?2 ??

Unicode編碼表示的字符是在編譯期間就轉(zhuǎn)換成了普通字符,它與普通轉(zhuǎn)義字符(如:\")是不一樣的,它們是在程序

被解析為各種符號(hào)之后才處理轉(zhuǎn)義字符序列。

?

21.?注釋中的Unicode轉(zhuǎn)義字符

如果程序中含有以下的注釋:// d:\a\b\util ,程序?qū)⒉荒芫幾g通過,原因是\u后面跟的不是四個(gè)十六進(jìn)制數(shù)字,但

編譯器在編譯時(shí)卻要把\u開頭的字符的字符看作是Unicode編碼表示的字符。

?

所以要注意:注釋中也是支持Unicode轉(zhuǎn)義字符的。

?

另外一個(gè)問題是不能在注釋行的中間含有 \u000A 表示換行的Unicode字符,因?yàn)檫@樣在編譯時(shí)讀到 \u000A 時(shí),表示

行結(jié)束,那么后面的字符就會(huì)當(dāng)作程序代碼而不在是注釋了。


22.?Windows與Linux上的行結(jié)束標(biāo)示符

Java代碼 ? ? 收藏代碼
  1. String?line?=?(String)System.getProperties().get( "line.separator" );??
  2. for ( int ?i?= 0 ;?i?<?line.length();i++){??
  3. ?System.out.println(( int )line.charAt(i));??
  4. }??

在Windows上運(yùn)行結(jié)果:
13
10

在Linux上運(yùn)行的結(jié)果:
10

在Windows平臺(tái)上,行分隔符是由回車(\r)和緊其后的換行(\n)組成,但在Unix平臺(tái)上通常使用單獨(dú)的換行(\n)

表示。


23.?輸出0-255之間的ISO8859-1符

Java代碼 ? ? 收藏代碼
  1. byte ?bts[]?=? new ? byte [ 256 ];??
  2. for ?( int ?i?=? 0 ;?i?<? 256 ;?i++)?{??
  3. ?bts[i]?=?( byte )?i;??
  4. }??
  5. //?String?str?=?new?String(bts,"ISO8859-1");//正確的做法 ??
  6. String?str?=? new ?String(bts); //使用操作系統(tǒng)默認(rèn)編碼方式編碼(XP?GBK) ??
  7. for ?( int ?i?=? 0 ,?n?=?str.length();?i?<?n;?i++)?{??
  8. ?System.out.print(( int )?str.charAt(i)?+? "?" );??
  9. }??

上面不會(huì)輸出0-255之間的數(shù)字串,正確的方式要使用new String(bts," ISO8859-1") 方式來解碼。

?

ISO8859-1是唯一能夠讓該程序按順序打印從0到255的整數(shù)的缺少字符集,這也是唯一在字符和字節(jié)之間一對一的映射

字符集。

?

通過java獲取操作系統(tǒng)的默認(rèn)編碼方式:

Java代碼 ? ? 收藏代碼
  1. System.getProperty( "file.encoding" ); //jdk1.4或之前版本 ??
  2. java.nio.charset.Charset.defaultCharset(); //jdk1.5或之后版本 ??

?
24.?String的replace()與replaceAll()

Java代碼 ? ? 收藏代碼
  1. System.out.println( "." .replaceAll( ".class" ,? "\\$" ));??

上面程序?qū)?. 替換成 \$,但運(yùn)行時(shí)報(bào)異常,主要原replaceAll的第二參數(shù)有兩個(gè)字符(\ $)是特殊字符,具有特殊

意思(\用來轉(zhuǎn)移 \ 與 $,$后面接數(shù)字表示反向引用)。另外,replaceAll的第一參數(shù)是正則表達(dá)式,所以要注意特

殊字符,正確的作法有以下三種:

Java代碼 ? ? 收藏代碼
  1. System.out.println( ".class" .replaceAll( "\\." ,? "\\\\\\$" ));??
  2. System.out.println( ".class" .replaceAll( "\\Q.\\E" ,? "\\\\\\$" ));??
  3. System.out.println( ".class" .replaceAll(Pattern.quote( "." ),?Matcher.quoteReplacement( "\\$" )));??

API對\、\Q與\E的解釋: ?
\? 引用(轉(zhuǎn)義)下一個(gè)字符 ?
\Q引用所有字符,直到 \E ?
\E結(jié)束從 \Q 開始的引用

?

JDK5.0新增了一些解決此問題的新方法:
java.util.regex.Pattern.quote(String s):使用\Q與\E將參數(shù)引起來,這些被引用的字符串就是一般的字符,哪怕

含有正則式特殊字符。
java.util.regex.Matcher.quoteReplacement(String s):將\與$轉(zhuǎn)換成能應(yīng)用于replaceAll第二個(gè)參數(shù)的字符串,

即可作為替換內(nèi)容。

String的replace(char oldChar, char newChar)方法卻不使用正則式,但它們只支持字符,而不是字符串,使用起來

受限制:

Java代碼 ? ? 收藏代碼
  1. System.out.println( "." .replace( '.' , '\\' )); //能將?.?替換成?\ ??
  2. System.out.println( "." .replace( '.' , '$' ));? //能將?.?替換成?$ ??

?
25.?一段程序的三個(gè)Bug

Java代碼 ? ? 收藏代碼
  1. Random?rnd?=? new ?Random();??
  2. StringBuffer?word?=? null ;??
  3. switch ?(rnd.nextInt( 2 ))?{??
  4. case ? 1 :??
  5. ?word?=? new ?StringBuffer( 'P' );??
  6. case ? 2 :??
  7. ?word?=? new ?StringBuffer( 'G' );??
  8. default :??
  9. ?word?=? new ?StringBuffer( 'M' );??
  10. }??
  11. word.append( 'a' );??
  12. word.append( 'i' );??
  13. word.append( 'n' );??
  14. System.out.println(word);??

上面的程序目的是等概率的打印 Pain、Gain、Main 三個(gè)單詞,但多次運(yùn)行程序卻發(fā)現(xiàn)永遠(yuǎn)只會(huì)打印 ain,這是為什

么?

?

第一個(gè)問題在于:rnd.nextInt(2)只會(huì)返回0、1 兩個(gè)數(shù)字,所以上面只會(huì)走case 1: 的分支語句,case 2: 按理是永

遠(yuǎn)不會(huì)走的。

第二個(gè)問題在于:如果case語句不以break結(jié)束時(shí),則一直會(huì)往向運(yùn)行,即直到執(zhí)行到break的case語句止,所以上面

的的語句每次都會(huì)執(zhí)行default分支語句。

第三個(gè)問題在于:StringBuffer的構(gòu)造函數(shù)有兩種可接受參數(shù)的,一個(gè)是StringBuffer(int capacity)、另一個(gè)是

StringBuffer(String str),上面用的是StringBuffer(char)構(gòu)造函數(shù),實(shí)質(zhì)上運(yùn)行時(shí)將字符型轉(zhuǎn)換成了int型,這樣

將字符當(dāng)作StringBuffer的初始容量了,而不是字符本身。

?

以下是修改后的程序片段:

Java代碼 ? ? 收藏代碼
  1. Random?rnd?=? new ?Random();??
  2. StringBuffer?word?=? null ;??
  3. switch ?(rnd.nextInt( 3 ))?{??
  4. case ? 1 :??
  5. ?word?=? new ?StringBuffer( "P" );??
  6. ? break ;??
  7. case ? 2 :??
  8. ?word?=? new ?StringBuffer( "G" );??
  9. ? break ;??
  10. default :??
  11. ?word?=? new ?StringBuffer( "M" );??
  12. ? break ; //?可以不要 ??
  13. ??
  14. }??
  15. word.append( 'a' );??
  16. word.append( 'i' );??
  17. word.append( 'n' );??
  18. System.out.println(word);??

java解惑你知多少(三)


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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

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

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

【本文對您有幫助就好】

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

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 通州区| 兰西县| 南华县| 盘锦市| 同仁县| 和龙市| 汉沽区| 阿瓦提县| 濮阳市| 余姚市| 辉南县| 台南县| 开阳县| 南汇区| 曲周县| 防城港市| 湘潭县| 彭水| 资源县| 吴桥县| 丹江口市| 新巴尔虎右旗| 米易县| 元江| 黎城县| 宁都县| 宝兴县| 和平区| 紫阳县| 民和| 县级市| 南部县| 额敏县| 西吉县| 夏河县| 黄冈市| 兰西县| 凌云县| 和静县| 太和县| 台北县|