型態

May 19, 2022

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

型態系統

基本上,Java 可區分為兩大型態系統:

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

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

Java 的基本型態主要可區分為整數、位元組、浮點數、字元與布林:

  • 整數

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

  • 位元組

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

  • 浮點數

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

  • 字元

Java 支援 Unicode,char 型態佔 2 個位元組,可用來儲存 UTF-16 Big Endian 的一個碼元(code unit),就現在而言,只要知道英文或中文字元可以直接寫在 ''char 儲存,也可以把 65535 以內的整數指定給 char

  • 布林

boolean 型態可表示 truefalse,分別代表邏輯的「真」與「假」,不用在意 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);
    }    
}

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

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

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

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

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

格式化輸出

System.out.println 會在標準輸出中顯示文字後換行,如果使用 System.out.print,輸出文字後不會換行,System.out.printf 會對輸出文字作格式化後再顯示在文字模式中。printf 的第一個引數(Argument)是字串,當中 %d%h%b 等是格式控制符號。以下列出一些常見的格式控制字元:

  • %%:因為 % 符號已被用為控制符號前置,就規定使用 %% 在字串中表示 %
  • %d:10 進位整數格式輸出,可用於 byteshortintlongByteShortIntegerLongBigInteger
  • %f:10 進位浮點數格式輸出,可用於 floatdoubleFloatDoubleBigDecimal
  • %e%E:科學記號浮點數格式輸出,提供的數必須是 floatdoubleFloatDoubleBigDecimal%e 表示輸出格式遇到字母以小寫表示,如 2.13e+12,%E 表示遇到字母以大寫表示。
  • %o:8 進位整數格式輸出,可用於 byteshortintlongByteShortIntegerLongBigInteger
  • %x%X:16 進位整數格式輸出,可用於 byteshortintlongByteShortIntegerLong、或 BigInteger%x 表示字母輸出以小寫表示,%X 則以大寫表示。
  • %s%S:字串格式符號。
  • %c%C:字元符號輸出,提供的數必須是 byteshortcharByteShortCharacterInteger%c 表示字母輸出以小寫表示,%C 則以大寫 表示。
  • %b%B:輸出 boolean 值,%b 表示輸出結果會是 truefalse%B 表示輸出結果會是 TRUEFALSE。非 null 值輸出是 trueTRUEnull 值輸出是 falseFALSE
  • %h%H:使用 Integer.toHexString(arg.hashCode()) 來得到輸出結果,如果 argnull,則輸出 null,也常用於 16 進位格式輸出。
  • %n:輸出平台特定的換行符號,如果 Windows 會置換為 "\r\n",如果是 Linux 會置換為 '\n',Mac OS 會置換為 '\r'

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

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

可以在輸出浮點數時指定精度,例如:

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

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

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

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

字面常量

在 Java 寫下一個值,該值稱為字面常量(Literal constant)。在整數字面常量表示上,除了 10 進位表示法之外,還有8進位或16進位表示。例如 12 這個值分別以 10 進位、16 進位與 8 進位表示:

jshell> 12    // 10 進位表示
$1 ==> 12

jshell> 0xC   // 16 進位表示,以 0x 開頭
$2 ==> 12

jshell> 014   // 8 進位表示,以 0 開頭
$3 ==> 12

浮點數除了使用小數方式直接表示外,也可以直接使用科學記號表示。例如以下都是表示 0.00123 的值:

jshell> 0.00123
$4 ==> 0.00123

jshell> 1.23e-3
$5 ==> 0.00123

要表示字元的話,必須使用 ' 符號括住字元,這會是個 char 型態。例如:

jshell> 'S'
$6 ==> 'S'

jshell> '林'
$7 ==> '林'

' 這個符號在語法上用來表示字元,若就是想表示 ' 這個字元呢?必須使用忽略(Escape)符號 \,編譯器看到 \ 會忽略下個字元,不視為程式語法的一部份。例如要表示 ' 就要用 \'

以下是常用的一些忽略符號:

  • \\:反斜線 \
  • \':單引號 '
  • \":雙引號 "
  • \uxxxx:以 16 進位數指定 char 的值,x 表示數字。
  • \xxx:以 8 進位數指定 char 的值,x 表示數字。
  • \b:倒退一個字元。
  • \f:換頁。
  • \n:換行。
  • \r:游標移至行首。
  • \t:跳格(按下 Tab 鍵的字元)。

撰寫整數或浮點數字面常量時,可以使用底線更清楚地表示某些數字。例如:

jshell> 1234_5678
$9 ==> 12345678

jshell> 3.141_592_653
$10 ==> 3.141592653

有時候,想以二進位方式表示某個值,可以用 0b 作為開頭。例如:

jshell> 0b101010101010  // 用二進位表示 10 進位整數 2730
$11 ==> 2730

上面的程式片段也可以結合底線,這樣就更清楚了:

jshell> 0b1010_1010_1010 // 用二進位表示 10 進位整數 2730
$12 ==> 2730

分享到 LinkedIn 分享到 Facebook 分享到 Twitter