1. 程式人生 > >關於b=++b和b = b += 1的問題探討

關於b=++b和b = b += 1的問題探討

問題一:byte b = 1; b = b += 1;   
問題二:byte b = 1; b = ++b;  

問題一和問題2中的結果在編譯時是沒有問題的,哪位朋友可以幫我解釋一下為什麼嗎?
byte b=1,這個我知道肯定是沒問題了,int型別的1自動轉化為了byte型別並賦值給了b,但是b + b+=1這個有點不太理解了,
b += 1是不是相當於b = b+1,如果是這樣的話,編譯應該有問題才對,b+1運算後的結果是int型別,需要強轉才能賦值給byte型別的。

第二個問題,b = ++b,先運算++再賦值,感覺也相當於b = b+1,為什麼這個編譯也不報錯呢
經過仔仔細細又看了兩遍老畢的“15-Java語言基礎(算術運算子_2&賦值運算子).avi”,已經有了答案了,如答案有不足之處,希望大家指出來:
一:byte b = 1; b = b += 1;   
二:byte b = 1; b = ++b;  
問題一:
    對於第一個運算,首先,byte b = 1;實際上這個值是編譯器先進行了一次檢查,範圍在byte範圍內,則編譯通過,
    同時將1這個int型別的值在底層轉化為了byte型別賦給了b;
    再說說b = b += 1;這個運算是將b += 1的計算結果賦給了b,所以我們只說b += 1的運算過程就行了,
    b += 1,其實等價於 b = (byte)(b+1);底層會對這個結果進行強轉的,所以它編譯的時候沒事,如果b是127,
    那麼加1後變成128了,成了int型別了,超過了byte型別的最大範圍了,怎麼辦?這時候底層會強轉,把int型別的
    前面三個高位丟棄,丟棄後,如果剩下的一位中,最高位為1,則取反加一,就成了負數了,如果最高位為0,直接把
    值賦給b
                        
問題二、
    b = ++b,這個運算的過程是,先進行++b的運算,再把運算後的結果賦給b,++b計算後是一個int型別的,
    不管結果等於多少,底層會進行一個強轉,也就是說++b就相當於 b = (byte)(b+1),所以這個編譯也沒有問題,但是如果你
    搞個byte b = 127; b = ++b;結果也會跟問題一一樣,大家可以測試一下

另外還有幾個類似的問題在此一起說明:

1.
    int count = 0;
    count = count + count++;
    System.out.println(count);
    2.
    int count = 0;
    count = count++ + count;
    System.out.println(count);
    3.
    int count = 0;
    for (int i = 0; i < 100; i++) {
    count = count + count++;
    }
    System.out.println(count);
    4.
    int count = 1;
    for (int i = 0; i < 100; i++) {
    count = count + count++;
    }
    System.out.println(count);

複製程式碼

    第一個問題: 要明白count = count + count++的結果,首先要知道兩個問題:
    第一個是這個運算的運算順序,第二個是count++操作做了什麼事,對於運算順序,肯定是先運算等式右邊的
    再賦值給左邊的變數,右邊的運算是從左到右算的,明白了這兩個問題再來看題就不復雜了. count = count +
    count++;先運算右邊,右邊從左到右算, 我們要是知道count++的結果就知道了右邊的結果了,
    count在跟左邊的count運算之前,會先進行一個複製,將原來的值複製一份,然後它本身的原值會自增,
    需要注意的是原值的自增跟複製後的資料是沒有關係的,自增後,原值變成1了, 這時候進行count +
    count++進行運算,但是count++參與運算的是複製出來的那份值而不是自增後的結果,
    由於等式右邊的左邊的count是在count++運算前就有值的,所以它是0,而count++的結果是0,所以 就是 0 + 0,
    然後將結果賦給了等式左邊的count,結果列印就是0

    第二個問題: 原理其實跟第一個問題差不多,但結果肯定是不一樣的,因為等式右邊的運算是要從左到右的,count++ + count,
    count先複製一份資料也就是0出來,然後進行自增這時候原值變為1了,而count++參與運算用的是複製出來的0參與
    運算的,所以count++ + count實際上就是 0 + 1,為什麼這裡是0+1而不是0+0呢,因為count++運算雖然用的是複製出來
    的那份資料,但是它本身的值已經自增到了1,而count++右邊的那個count拿的是自增後的原值也就是1, 所以這個列印結果是1

    第三個問題: 如果你第一第二個問題已經看懂了,我相信第三個問題已經不言自明瞭,count = count + count++;列印的結果
    其實就相當於count = count + count;雖然兩者底層運算有點差異,但結果是一樣的, 所以這個for迴圈不管有多少次
    結果都是0 = 0 + 0,結果都列印為0

    第四個問題: 原理也是一樣的因為count = count + count++的結果就相當於count = count + count;
    所以再來看第四個問題的結果就不為怪了,但是第四個問題有些人可能會感到奇怪,因為結果是0,如果我們自己算也會感到奇怪,
    count首先等於1,for迴圈第一次1 = 1 + 1++結果為2(不解釋了吧),再運算的資料會越來越大為什麼會為0呢?
    我也感到納悶,但我知道一旦這個count有一次結構為0,後面的所有for迴圈計算出的結果都為0了,
    所以我們找到為0的時候for迴圈中的i等於多少,
    經測算i為31的時候,結果為0,而i為30的時候count等於-2147483648,二進位制為
    10000000000000000000000000000000,這時候count + count++, 就相當於count *2
    了(兩個相同的資料相加相當於乘以2, 這個不用解釋吧),乘以2就相當於左移1位,結果為0,所以就出現了這樣的結果了