型態


在Java的世界中,並非每個東西抽象化為物件,你還是要面對系統的一些特性,例如,你還是要意會到記憶體長度有限的問題,所以程式執行時遇到123這個整數時,你還是要想一下,用多少長度的記憶體來儲存它會比較經濟。基本上,Java可區分為兩大型態系統:

  • 基本型態(Primitive type)
  • 類別型態(Class type),亦稱參考型態(Reference type)

這邊先解釋基本型態,之後會說明類別型態。

所謂基本型態,就是你在使用時,得考慮一下資料用多少記憶體長度來存比較經濟,利用程式語法告訴JVM,然後由JVM自動為你在記憶體中配置與管理。在Java中的基本型態主要可區分為整數、位元組、浮點數、字元與布林:

  • 整數

可細分為short整數(佔2個位元組)、int整數(佔4個位元組)與long整數(佔8個位元組)。不同長度的整數,可儲存的整數範圍也不同。long整數佔的記憶體長度比int整數來得多,可表示的整數範圍也就比int整數大。同樣的,int整數可表示的整數範圍也比短整數來得大。

  • 位元組

byte型態顧名思義,長度就是一個位元組,在需要逐位元組處理資料時(例如影像處理、編碼處理等),就會使用byte型態,若用於表示整數,byte可表示-128到127的整數。

  • 浮點數

主要用來儲存小數數值,可分為float浮點數(佔4個位元組)與double浮點數(佔8個位元組),double浮點數使用的記憶體空間比float浮點數來得多,可表示的精確度也比較大。

  • 字元

char型態用來儲存'A''B''林'等字元符號。在JDK8中,Java的字元採Unicode 6.2編碼,JVM實作採UTF-16 Big Endian,所以每個字元型態佔兩個位元組,中文字元與英文字元在Java中同樣都是用兩個位元組儲存。

有關編碼、Unicode、UTF 等,可以參考 哪來的純文字檔?,以及 Unicode 與 UTF

  • 布林
boolean型態可表示truefalse,分別代表邏輯的「真」與「假」。在Java中不用在意boolean型態的長度,因為你也無法將boolean型態與其它型態作運算。


每種型態佔有的記憶體長度不同,可儲存的數值範圍也就不同。例如int型態的記憶體空間是4個位元組,所以可儲存的整數範圍為-2147483648至2147483647,如果儲存值超出型態範圍稱之為溢值(Overflow),會造成程式不可預期的結果。不用記憶各種型態可儲存的數值範圍,可以透過API來得知。例如:

package cc.openhome;

public class Range {
    public static void main(String[] args) {
        // byte、short、int、long 範圍
        System.out.printf("%d ~ %d%n", 
                Byte.MIN_VALUE, Byte.MAX_VALUE);
        System.out.printf("%d ~ %d%n", 
                Short.MIN_VALUE, Short.MAX_VALUE);
        System.out.printf("%d ~ %d%n", 
                Integer.MIN_VALUE, Integer.MAX_VALUE);
        System.out.printf("%d ~ %d%n", 
                Long.MIN_VALUE, Long.MAX_VALUE);
        // float、double 精度範圍
        System.out.printf("%d ~ %d%n", 
                Float.MIN_EXPONENT, Float.MAX_EXPONENT);
        System.out.printf("%d ~ %d%n", 
                Double.MIN_EXPONENT, Double.MAX_EXPONENT);
        // char 可表示的 Unicode 範圍
        System.out.printf("%h ~ %h%n", 
                Character.MIN_VALUE, Character.MAX_VALUE);
        // boolean 的兩個值
        System.out.printf("%b ~ %b%n", 
                Boolean.TRUE, Boolean.FALSE);
    }    
}

對於初學Java,會看到一些新的語法與API在裏頭,以下逐一解釋。


你在程式中看到//符號,這是Java程式中的單行註解,註解是用來說明或記錄程式中一些注意事項,編譯器會忽略該行//符號之後的文字,對編譯出來的程式不會有任何影響,另一個註解符號是/**/包括的多行註解。例如:

/* 作者:良葛格
   功能:示範printf()方法
   日期:2011/7/23
 */
public class Demo {
...

編譯器會忽略/**/間的文字,不過以下使用多行註解的方式是不對的:

/*  註解文字1……bla…bla
    /*
        註解文字2……bla…bla
    */
*/

編譯器會以為倒數第二個*/就是註解結束的時候,因而對最後一個*/就會認為是錯誤的語法,這時就會出現編譯錯誤的訊息。


在第一個Java程式顯示Hello World時,使用了System.out.println(),這會在標準輸出中顯示文字後換行,如果使用System.out.print(),則輸出文字後不會換行。那麼System.out.printf()是什麼?printf()是JDK5之後才有API,f就是format的意思,也就是格式化,用在System.out上,就是對輸出文字作格式化後再顯示在文字模式中。printf()的第一個引數(Argument)是字串,當中%d%h%b等是格式控制符號。以下列出一些常見的格式控制字元:

符號
說明
%% 因為%符號已經被用來作為控制符號前置,所以規定使用%%才能在字串中表示%
%d 以10進位整數格式輸出,可用於byte、short、int、long、Byte、Short、 Integer、Long或BigInteger
%f 以10進位浮點數格式輸出,可用於float、double、Float、Double或BigDecimal
%e, %E 以科學記號浮點數格式輸出,提供的數必須是float、double、Float、 Double或BigDecimal%e表示輸出格式遇到字母以小寫表示,如2.13 e+12,%E表示遇到字母以大寫表示。
%o 以8進位整數格式輸出,可用於byte、short、int、long、Byte、Short、 Integer、Long或BigInteger
%x, %X 以16進位整數格式輸出,可用於byte、short、int、long、Byte、Short、 Integer、Long或BigInteger%x表示字母輸出以小寫表示,%X則以大寫表示。
%s, %S 字串格式符號。
%c, %C 以字元符號輸出,提供的數必須是byte、short、char、Byte、Short、Character或Integer%c表示字母輸出以小寫表示,%C則以大寫表示。
%b, %B 輸出boolean值,%b表示輸出結果會是true或false,%B表示輸出結果會是TRUE或FALSE。非null值輸出是true或TRUE,null值輸出是false或FALSE。
%h, %H 使用Integer.toHexString(arg.hashCode())來得到輸出結果,如果argnull,則輸出null,也常用於想得到16進位格式輸出。
%n 輸出平台特定的換行符號,如果Windows下會置換為"\r\n",如果是Linux下則會置換為'\n',Mac OS下會置換為'\r'

printf()方法的第二個引數開始,會依序置換掉第一個引數的格式控制符號。Byte、Short、Integer、Long、Float、Double、Character、Boolean,這些都是java.lang套件下的類別,下一章就會談到,這些類別都是基本型態的包裹器(Wrapper),至於MAX_VALUE、MIN_VALUE、MIN_EXPONENT、MAX_EXPONENT、TRUE、FALSE等,都是這些類別上的靜態(static)成員(其實System中的out也是),別擔心,之後還會解釋何謂靜態成員,就目前來說,直接使用就對了。

這個範例的輸出結果如下:

-128 ~ 127
-32768 ~ 32767
-2147483648 ~ 2147483647
-9223372036854775808 ~ 9223372036854775807
-126 ~ 127
-1022 ~ 1023
0 ~ ffff
true ~ false

可以在輸出浮點數時指定精度,例如以下這行的執行結果會輸出" example:19.23":

System.out.printf("example:%.2f%n", 19.234);

也可以指定輸出時,至少要預留的字元寬度,例如:

System.out.printf("example:%6.2f%n", 19.234);

由於預留了6個字元寬度,不足的部份要由空白字元補上,所以執行結果會輸出" example: 19.23"(19.23只佔五個字元,所以補了一個空白在前端)。