Java‎ > ‎

Primitive Data Type

在程式中,我們需要去紀錄一些數值、資料,或是表示某些狀態,而在程式語言中負責這樣子的東西,我們稱之為變數。用較「專業」的說法,就是程式在執行時,會在記憶體裡頭空出一些空間,用來存放資料以便程式能夠運作。

既然扯到記憶體,就理所當然的會扯到資料型態(data type)以及資料表示法。在 Java 當中內建好的資料型態(primitive data type)有下列幾種:

 資料型態  記憶體中的 bit 量  範圍
 boolean  8  true, false (只有兩個)
 char  16  '\u0000'~'\uffff' (Unicode 字集)
 byte  8  整數:-128~127
 short  16  整數:-32768~32767
 int  32  整數:-2147483648~2147483647
 long  64  -9223372036854775808~9223372036854775807
 float [註1]
 32  ±1.4E-45~±3.4028235E+38
 double  64  ±4.9E-324~±1.79769313486231570E+308

這種顏色欄位的資料型態都是整數,差別在於範圍的大小;同樣的,這種顏色欄位的資料型態都是可以帶有小數點的實數,差別在於範圍的大小。如果你的計算機概論學的還不錯,那整數的部分只要記得需要的 bit 數就可以了,後頭的範圍自然很容易推的出來。至於實數... 誰管它什麼範圍...(不要叫我背 or 算 :P),不過要這裡提一下,以 float 為例,「± 1.4E-45~±3.4028235E+38」的意思是「1.4E-45~3.4028235E+38」以及「-1.4E-45~- 3.4028235E+38」兩個範圍的聯集,這邊只是偷懶的縮寫,相信記算機概論學過的都知道為什麼是這樣,忘記的就快快去翻書吧~ ccc

既然每種不同資料型態有不同的範圍,而 Java 又是一種 Strong Type 的語言,所以下面這個程式的錯誤就一定要避免囉:
class error1{
public static void main(String args[]){
short x_short;
int x_int=5;

x_short=x_int;
System.out.println(x_short);
}//end of main()
}//end of class error1

在 compile 的時候就會出現錯誤,告訴你 compiler 沒有辦法把 int 轉換成 short。遇到這種情形,你只要這樣子改就沒問題了:
class amend_error1{
public static void main(String args[]){
short x_short;
int x_int=5;

x_short=(short) x_int;
System.out.println(x_short);
}//end of main()
}//end of class amend_error1

(short) 會幫你把 x_int 的數值強制轉換成 short 的格式。當然,明明 short 的資料型態最大只能到 32767,你要把一個在 short 範圍以外的值硬是轉換成 short 的格式,可就不要期望出來的結果是你想要的:
class error2{
public static void main(String args[]){
short x_short;
int x_int=40000;

x_short=(short) x_int;
System.out.println(x_short);
}//end of main()
}//end of class error2
  這個程式在 compile 以及執行的時候都不會有問題,但是 output 的值是 -25536。由此觀之,為了程式的堅固耐用,還是不要隨意使用「(short)」這類的指令。
  其實,Java 並沒有很徹底的 Strong Type,因為不是所有不同資料型態的變數扯在一起就會出問題,以下提供一個小小表格,給大家參考著用:

   byte  short  char  int  long  float  double
 byte    Y  C  Y  Y  Y  Y
 short  C    C  Y  Y  Y  Y
 char  C  C    Y  Y  Y  Y
 int  C  C  C    Y  Y*  Y
 long  C  C  C  C    Y*  Y*
 float  C  C  C  C  C    C
 double  C  C  C  C  C  C  
  • C 表示需要加入強制轉換的指令,才能正常運作。
  • Y 表示 JAVA 會幫你作轉換的動作。
  • Y* 跟 Y 的差別:JAVA 不保證轉換後數值的精準度(因為資料儲存方式的關係)。
我們大致上可以歸類出一個結論:在 Java 中,如果(資料型態)範圍比較小的變數可以把值存入(資料型態)範圍比較大的變數、(資料型態)沒有小數點的變數可以把值存入(資料型態)有小數點的變數,而不需要在程式碼中加入轉換的指令(忽略 Y* 的精準度問題);反之,則需要經過轉換的過程,因為資料型態不同的關係,轉換完之後的值可能完全偏差掉。

另外,Java 還有一個特別的地方。如果你把一堆變數作算術運算、遞加遞減、bitwise 運算,只要這堆變數當中,有一個以上是〔double〕型態,那整個式子最後的運算結果的傳回值也會是〔double〕型態,「〔〕」中型態辨別的依序是 doublefloatlong;最後,如果式子當中沒有上面三種資料型態的變數,那麼「傳回值的資料型態就會是 int」。請特別注意這點,傳回值只會有這四種資料型態,即使你是把一堆 charbyteshort 變數下去運算,傳回值還是 int 的型態[註2]。請看下面這個程式範例:
class error3{
public static void main(String args[]){
byte a, c=3, b=10, d=-5;

a=b+c-d;
System.out.println(a);

}//end of main()
}//end of class error3

這個程式在 compiler 的時候,會出現這樣子的錯誤訊息:
C:\programs\Java>javac error3.java
error3.java:5: Incompatible type for =. Explicit cast needed to convert int to byte.
    a=b+c-d;
     ^
1 error

所以,在這裡請特別注意喔~

[註1] 這裡的數據跟數值表示方都是取自於 O'REILLY 出版的第三版《JAVA 技術手冊》p.28 頁。

但是在 float 的地方出了一點問題,因為上頭寫的數據跟俗稱「綠色螞蟻書」的《JAVA HOW TO PROGRAM 3rd Edition》(由 PRENTICE HALL 出版,DEITEL 系列)p.144 所寫的不同。

在沒有旺盛的好奇心去查詢 IEEE 754 的規格 or SUN 網站的資料,這裡採用 JAVA 技術手冊的資料,原因無他,因為這本書有標明 underflow 的上下界,而另一本書沒有。特別在此註明一下,以示負責。

[註2] 這裡不考慮 boolean 型態。 
Comments