前言
短文速讀,這将是一個系列文章。自己寫了很多文章,也看了很多文章。發現很多都是收藏不看系列。當然有時間的時候,的确會把收藏的文章找出來好好的學習一番。但是大多數文章仿佛石沉大海,失去了應有的價值。
是以萌生了這個系列的想法,系列文章的特點:以一些日常開發中不起眼的基礎知識點為核心,圍繞此包裹通俗易懂的文字。盡量用少思考的模式去講述一個知識。讓我們能夠真正在碎片化的時間裡學到東西!
出場角色
小A:剛踏入Java程式設計之路...
MDove:一個快吃不上飯的Android開發...
正題
小A:MDove,最近我有一個不成熟的小疑問,不知道當講不當講。
MDove:不成熟那就别問了...
小A:額錯了,額真滴錯了。額從一開始就不應該學Java...
MDove:問、問、問...
小A:a=a+b和a+=b。這倆者有什麼差別呀?沒看出來有什麼差別啊!
MDove:你所說的沒差別,是這樣吧?
int a = 1;
int b = 2;
a = a + b;
a += b;
MDove:那你有沒有換過别的寫法呢?比如把b的類型變一下:
float b = 2F;
MDove:怎麼樣,看出來效果了吧。沒看出來??OK,那我就貼上效果:

編譯不能通過
MDove:這樣就能看明白了吧?b提升了類型之後。會發現
a = a + b
是沒辦法編譯通過的,需要強制類型轉換才可以。但是我們的
a + = b
卻可以,這是為什麼呢?其實很簡單。讓我們反編譯一下這個class檔案,就可以很清晰的給出答案:
public void fun() {
int a = 1;
float b = 2F;
a += b;
}
// 反編譯class的内容
public void fun() {
byte var1 = 1;
float var2 = 2.0F;
int var10000 = (int)((float)var1 + var2);
}
MDove:是以它們二者的差別就很清楚了吧?在這種a比b類型範圍要小的情況下。
a = a + b;
需要強制類型轉換,也就是我們常寫的:
a = (int) (a+b);
而我們的
a += b;
被我們的編譯器在編譯期做了一些小手腳。也就是編譯器幫我們進行了強制類型轉化。
小A:原來是這樣,那強制類型轉換會帶來什麼問題呢?
MDove:解答這個問題,讓我們先來看一張圖:
image
MDove:強制類型轉化,一般會帶來精度丢失的問題。這裡float的範圍太大,我們就用byte和short來示範,強制類型帶來的問題:
public void fun() {
byte a = 1;
short b = 127;
a=(byte) (a+b);
System.out.println(a);
}
MDove:System打出的内容,應該知道是什麼吧?沒錯是-128。強制類型帶來的問題一目了然了吧。
小A:怎麼會是-128呢?
MDove:OK,接下來,我來解釋一下,為什麼會是-128這麼一個奇怪的數字。首先,我們都知道基本類型在堆中所占的位元組如下表。
小A:不對呀?我記得基本類型是存放在棧中的呀?
MDove:這種說法并不錯,但不全面。存放在堆中還是在棧中,是取決于這個變量聲明的位置。如果是局部變量,則會存放在棧幀中。但是如果是成員變量(全局變量),那麼就會存放在堆中。此外存放在棧中,基本類型所占的位元組是固定:如果是32位計算機那麼就是4位元組;64位便是8位元組。
類型 | 所占位元組 |
---|---|
byte | 1位元組 |
short | 2位元組 |
int | 4位元組 |
long | 8位元組 |
char | |
float | |
double |
MDove:解釋完所占位元組的問題,咱們繼續。由上邊可知byte占1位元組,那麼也就是8位,如果每一位都為1(11111111),那麼理論上就是它所能表示的最大内容。
小A:那應該是255呀!
MDove:實際不然,因為正負的原因,計算機中使用補碼的形式表示二進制,高1位表示符号位(0為正,1為負)。是以對于8位來說,最大隻能是01111111,也就是127。(0表示它為正)
MDove:而我們剛才的那個計算
byte a = 1; short b = 127; a=(byte) (a+b);
不考慮類型轉換,那麼a+b妥妥的等于128。并且對于所占2位元組的short來說那就是
00000000 10000000
。但是我們強制類型轉化成了byte,這時做了一件事情,那就是高1位元組的内容全部砍掉,也就是隻剩下了
10000000
。
MDove:按我們剛才所說,高1位的内容表示正負。1為負。
小A:!!!如果1為負,那System.out應該是0才對啊。
MDove:一看你二進制就沒有好好學。對于含有補碼形式的
10000000
,我們要用補碼的方式去計算。計算套路如下:高1位為1,那麼這是數就是負數。想要知道是負幾,我們需要将
10000000
按位取反,也就是
01111111
。還沒完,此時還要再加1,也就是
10000000
。現在得到的這個數是幾,那麼就是負幾,
10000000
是十進制的128,是以補碼形式的
10000000
也就是:-128。
MDove:這樣解釋是不是就知道強制類型轉換帶來的問題,以及為什麼強制類型轉化後的byte變成了-128了吧。
小A:好難學...我想回家種地...
小A媽:崽,别學程式設計啦,趕緊回家收玉米了。
劇終
這裡是一幫應屆生共同維護的公衆号,内容是我們在從應屆生過渡到開發這一路所踩過的坑,以及我們一步步學習的記錄,如果感興趣的朋友可以關注一下,一同加油,一同努力!!
個人公衆号:IT面試填坑小分隊