<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    [轉]Java語言的細節

    Java作為一門優秀的面向對象的程序設計語言,正在被越來越多的人使用。本文試圖列出作者在實際開發中碰到的一些Java語言的容易被人忽視的細節,希望能給正在學習Java語言的人有所幫助。
    ?
    1,拓寬數值類型會造成精度丟失嗎?
    ??? Java語言的8種基本數據類型中7種都可以看作是數值類型,我們知道對于數值類型的轉換有一個規律:從窄范圍轉化成寬范圍能夠自動類型轉換,反之則必須強制轉換。請看下圖:
    byte-->short-->int-->long-->float-->double
    char-->int
    我們把順箭頭方向的轉化叫做拓寬類型,逆箭頭方向的轉化叫做窄化類型。一般我們認為因為順箭頭方向的轉化不會有數據和精度的丟失,所以Java語言允許自動轉化,而逆箭頭方向的轉化可能會造成數據和精度的丟失,所以Java語言要求程序員在程序中明確這種轉化,也就是強制轉換。那么拓寬類型就一定不會造成數據和精度丟失嗎?請看下面代碼:
    int i=2000000000;
    int num=0;
    for(float f=i;f<i+50;f++){
    ??? num++;
    }
    System.out.println(num);
    請考察以上代碼輸出多少?
    如果你回答50 ,那么請運行一下,結果會讓你大吃一驚!沒錯,輸出結果是0,難道這個循環根本就沒有執行哪怕一次?確實如此,如果你還不死心,我帶你看一個更詫異的現象,運行以下代碼,看輸出什么?
    int i=2000000000;
    float f1=i;
    float f2=i+50;
    System.out.println(f1==f2);
    ??? 哈哈,你快要不相信你的眼睛了,結果竟然是true;難道f1和f2是相等的嗎?是的,就是這樣,這也就能解釋為什么上一段代碼輸出的結果是0,而不是50了。那為什么會這樣呢?關鍵原因在于你將int值自動提升為float時發生了數據精度的丟失,i的初始值是2000000000,這個值非常接近Integer.MAX_VALUE,因此需要用31位來精確表示,而float只能提供24位數據的精度(另外8位是存儲位權,見IEEE745浮點數存儲規則)。所以在這種自動轉化的過程中,系統會將31位數據的前24位保留下來,而舍棄掉最右邊的7位,所以不管是2000000000還是2000000050,舍棄掉最右邊7位后得到的值是一樣的。這就是為什么f1==f2的原因了。
    ??? 類似的這種數值拓寬類型的過程中會造成精度丟失的還有兩種情況,那就是long轉化成float和long轉化成double,所以在使用的時候一定要小心。
    ?
    2,i=i+1和i+=1完全等價嗎?
    ??? 可能有很多程序員認為i+=1只是i=i+1的簡寫方式,其實不然,它們一個使用簡單賦值運算,一個使用復合賦值運算,而簡單賦值運算和復合賦值運算的最大差別就在于:復合賦值運算符會自動地將運算結果轉型為其左操作數的類型。看看以下的兩種寫法,你就知道它們的差別在哪兒了:
    ? (1) byte i=5;
    ????? i+=1;
    ? (2) byte i=5;
    ????? i=i+1;
    ??? 第一種寫法編譯沒問題,而第二種寫法卻編譯通不過。原因就在于,當使用復合賦值運算符進行操作時,即使右邊算出的結果是int類型,系統也會將其值轉化為左邊的byte類型,而使用簡單賦值運算時沒有這樣的優待,系統會認為將i+1的值賦給i是將int類型賦給byte,所以要求強制轉換。理解了這一點后,我們再來看一個例子:
    ? byte b=120;
    ? b+=20;
    ? System.out.println("b="+b);
    ? 說到這里你應該明白了,上例中輸出b的值不是140,而是-116。因為120+20的值已經超出了一個byte表示的范圍,而當我們使用復合賦值運算時系統會自動作類型的轉化,將140強轉成byte,所以得到是-116。由此可見,在使用復合賦值運算符時還得小心,因為這種類型轉換是在不知不覺中進行的,所以得到的結果就有可能和你的預想不一樣。
    ?
    3,位移運算越界怎么處理
    ??? 考察下面的代碼輸出結果是多少?
    ??? int a=5;
    ??? System.out.println(a<<33);
    ??? 按照常理推測,把a左移33位應該將a的所有有效位都移出去了,那剩下的都是零啊,所以輸出結果應該是0才對啊,可是執行后發現輸出結果是10,為什么呢?因為Java語言對位移運算作了優化處理,Java語言對a<<b轉化為a<<(b%32)來處理,所以當要移位的位數b超過32時,實際上移位的位數是b%32的值,那么上面的代碼中a<<33相當于a<<1,所以輸出結果是10。
    ?
    4,判斷奇數
    ? 以下的方法判斷某個整數是否是奇數,考察是否正確:
    ?? public boolean isOdd(int n){
    ?????? return (n%2==1);
    ?? }
    ?? 很多人認為上面的代碼沒問題,但實際上這段代碼隱藏著一個非常大的BUG,當n的值是正整數時,以上的代碼能夠得到正確結果,但當n的值是負整數時,以上方法不能做出正確判斷。例如,當n=-3時,以上方法返回false。因為根據Java語言規范的定義,Java語言里的求余運算符(%)得到的結果與運算符左邊的值符號相同,所以,-3%2的結果是-1,而不是1。那么上面的方法正確的寫法應該是:
    ?? public boolean isOdd(int n){
    ?????? return (n%2!=0);
    ?? }
    ?
    5,可以讓i!=i嗎?
    在本題中,要求你聲明一個i值,使得以下程序輸出"No i!=i":
    //在此聲明i,并賦值。
    if(i==i){
    ????? System.out.println("Yes i==i");
    ? }else{
    ????? System.out.println("No i!=i");
    ? }
    ?
    ??? 當你看到這個命題的時候一定會以為我瘋了,或者Java語言瘋了。這看起來是絕對不可能的,一個數怎么可能不等于它自己呢?或許就真的是Java語言瘋了,不信請將i做出以下聲明,再運行上面的代碼。
    ? double i=0.0/0.0;
    ??? 上面的代碼輸出"No i!=i",為什么會這樣呢?關鍵在0.0/0.0這個值,在IEEE 754浮點算術規則里保留了一個特殊的值用來表示一個不是數字的數量。這個值就是NaN("Not a Number"的縮寫),對于所有沒有良好定義的浮點計算都將得到這個值,比如:0.0/0.0;其實我們還可以直接使用Double.NaN來得到這個值。在IEEE 754規范里面規定NaN不等于任何值,包括它自己。所以就有了i!=i的代碼。
    ?
    6,2.0-1.1==0.9嗎?
    ?考察下面的代碼:
    ?double a=2.0,b=1.1,c=0.9;
    ?if(a-b==c){
    ?? System.out.println("YES!");
    ?}else{
    ?? System.out.println("NO!");
    ?}
    以上代碼輸出的結果是多少呢?你認為是“YES!”嗎?那么,很遺憾的告訴你,不對,Java語言再一次欺騙了你,以上代碼會輸出“NO!”。為什么會這樣呢?其實這是由實型數據的存儲方式決定的。我們知道實型數據在內存空間中是近似存儲的,所以2.0-1.1的結果不是0.9,而是0.88888888889。所以在做實型數據是否相等的判斷時要非常的謹慎。一般來說,我們不建議在代碼中直接判斷兩個實型數據是否相等,如果一定要比較是否相等的話我們也采用以下方式來判斷:
    ? if(Math.abs(a-b)<1e-5){
    ???? //相等
    ? }else{
    ??? //不相等
    ? }
    上面的代碼判斷a與b之差的絕對值是否小于一個足夠小的數字,如果是,則認為a與b相等,否則,不相等。

    posted on 2008-06-13 14:41 金家寶 閱讀(489) 評論(2)  編輯  收藏 所屬分類: Java

    評論

    # re: [轉]Java語言的細節 2008-06-13 15:54 ~上善若水~

    傳智播客ajax全套內部視頻獨家發布,免費下載

    1.ajax 入門

    2.ajax 原理

    3.ajax 簡單實例

    4.ajax 無限級聯動菜單

    5.ajax 簡易聊天室

    6.ajax 開源框架簡介

    7.DWR 框架源碼分析一

    8.DWR 框架源碼分析二

    9.DWR 框架源碼分析三

    10.DWR 框架源碼分析四

    11.DWR框架源碼分析五

    12.SSH + DWR完成商城驅動

    13. Extjs 簡介

    14 Extjs&nbsp; 簡單實例

    15.SSH + Extjs 開發系列之OA一

    16. SSH + Extjs 開發系列之OA二

    17. SSH + Extjs 開發系列之OA三

    18. SSH + Extjs 開發系列之OA四

    19 .SSH + Extjs 開發系列之OA五

    20.&nbsp;SSH + Extjs 開發系列之OA六

    21. SSH + Extjs 開發系列之OA七

    22.&nbsp;SSH + Extjs 開發系列之OA八

    23.SSH + Extjs 開發系列之OA九

    24.SSH + Extjs 開發系列之OA十

    25. ajax 前景之我見

    下載地址:http://www.ibeifeng.com/read.php?tid=2338&u=5043  回復  更多評論   

    # re: [轉]Java語言的細節 2008-06-15 13:50 ZelluX

    Java Puzzlers上這種問題很多  回復  更多評論   

    主站蜘蛛池模板: 女人18毛片a级毛片免费| 免费A级毛片无码视频| 麻豆国产VA免费精品高清在线| 亚洲国产电影在线观看| 16女性下面扒开无遮挡免费| 亚洲视频在线一区二区三区| 免费国产黄网站在线观看视频| 亚洲黄色三级视频| 亚洲视频免费在线看| 亚洲中文字幕无码av在线| 国产精品美女午夜爽爽爽免费| 久久精品国产亚洲AV忘忧草18| 免费无码精品黄AV电影| 午夜亚洲WWW湿好爽| 亚洲综合激情另类专区| 成全动漫视频在线观看免费高清版下载 | 久久国产免费观看精品| 亚洲成AV人片在线观看WWW| 99久9在线|免费| 亚洲xxxxxx| 日产国产精品亚洲系列| a在线视频免费观看在线视频三区 a毛片成人免费全部播放 | 亚洲黄色片免费看| 一二三四视频在线观看中文版免费 | 久久精品国产精品亚洲| 久久爰www免费人成| 亚洲AV无码成人专区| 免费国产真实迷j在线观看| 两个人看的www免费视频中文| 亚洲视频在线观看| 18禁成年无码免费网站无遮挡 | 亚洲av午夜福利精品一区人妖| 国产91免费视频| 污视频网站在线免费看| 亚洲精品私拍国产福利在线| 成人毛片18女人毛片免费视频未 | 亚洲精品免费视频| 亚洲国产欧美国产综合一区 | 亚洲午夜电影在线观看高清| 国产成人精品123区免费视频| 国产免费阿v精品视频网址|