[Groovy] 程式設計教學:資料型別 (Data Type)

【分享本文】
Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

    資料型別 (data type) 用來規範變數在程式中相對應的操作;例如,數字型態資料可以加減乘除,布林型態資料可進行邏輯運算等。本文介紹 Groovy 的資料型別。

    萬物皆物件 (Everything is Object)

    在 Java 中,型別分為基礎型別 (primitives) 和參考型別 (references) 兩種型別,差別在於後者可以使用物件導向語法,而前者不行。在 Groovy 中,沒有這樣的區分,所有的值皆為物件 (everything is object)。

    在以下例子中,我們使用整數 3times 方法 (method) 重覆執行三次程式:

    3.times {
        println "Hello World"
    }

    這個程式會印出三行 "Hello World" 字串;因為 3 是一個整數物件 (object),可以呼叫 times 方法。這是從 Ruby 吸收來的物件導向式語法,一開始可能會覺得不太習慣,寫一陣子 Groovy 後就會覺得這種寫法相當有用。

    Groovy 對於物件的支援是透過一層 wrapper 將基礎型別包成參考型別,這個過程是自動轉換的,程式設計者不需手動處理這些 wrapper 類別。

    內建型別

    Groovy 沿用 Java 的型別系統,以下是常用的基礎型別 (base type):

    • 布林 (bool)
    • 字元 (char)
    • 數字 (Number)
      • 整數 (Integer)
        • Byte
        • Short
        • Integer
        • Long
        • BigInteger
      • 浮點數 (Floating-point number)
        • Float
        • Double
        • BigDecimal
    • 字串 (String)
      • String
      • GString

    所謂的基礎型別是指在這類型態的資料概念上是單一的 (atomic)。但在 Groovy 中,即使是基礎型別,仍然可用物件導向語法,這是從 Ruby 吸收而來的特性。

    此外,常見的複合型別如下:

    • 陣列 (array)
    • 串列 (list)
    • 映射 (map)

    複合型別會有其基礎型別,像是以字串為元素 (element) 的串列。

    除了使用現有的型別,Groovy 使用沿用 Java 的物件系統製作新的型別,但加上了 Groovy 特有的改進。

    布林 (Boolean)

    布林包括 truefalse 兩種值,用來表示邏輯上的真與假。不過,重要的是知道那些值會判定為 false,這類值稱為 falsy value。如下:

    • false
    • 數字為零 0
    • 空字串 ""
    • 空物件 null
    • 空陣列 (array)
    • 空映射 (map)
    • 空集合 (collection)

    除了 falsy value 外,其他的值本身會判定為真。

    另外,可在類別中實作 asBoolean 方法 (method),有實作這個方法的物件可直接判定物件的真假。以下例子摘自 Groovy 官網:

    class Color {
        String name
    
        boolean asBoolean(){
            name == 'green' ? true : false
        }
    }

    數字 (Number)

    雖然 Groovy 的數字有許多種型別,但不太需要擔心要使用那一個型別,因 Groovy 會自動轉換。如以下實例:

    def num = 2
    
    assert num instanceof java.lang.Integer
    
    num = num ** 100
    
    assert num instanceof java.math.BigInteger

    原先變數 num 是整數,但在運算後,超過整數的範圍,就自動轉為 Java 大數 (java.math.BigInteger 型別);這個特性在 Python 和 Ruby 等語言都有。

    字串 (String)

    Groovy 的字串,除了承接原有的 Java 字串的功能,也加上一些更方便的語法糖。例如,以下的 Java 程式將字串相接起來:

    // Java code
    public class StringDemo {
        public static void main(String[] args) {
            String name = "Michael";
    
            // String concatenation
            System.out.println("Hello " + name);
        }
    }

    但是在 Groovy 中,可以用更簡潔的字串安插 (string interpolation) 語法,如下例:

    def name = "Michael"
    
    println "Hello ${name}"

    在 Groovy 中,字串分為以下數種

    • 單引別字串
    • 雙引號字串
    • 三重單引號字串
    • 三重雙引號字串

    單引號字串和雙引號字串的差別,在於雙引號字串有字串安插的特性,而單引號則無。如下例:

    def name = "Michael"
    
    assert 'Hello ${name}' == 'Hello ${name}'
    assert "Hello ${name}" == 'Hello Michael'

    而三重引號字串則是用比較簡潔的方式表示多行字串,如下例:

    def name = "Michael Chen"
    def job = "Programmer"
    
    def msg = """\
    Name: ${name}
    Job: ${job}
    """
    
    print msg

    同樣地,雙引號字串有字串安插,單引號則無。

    Groovy 對字串的外加功能,是因為 Groovy 另外實做了 GString 型別。在 Groovy 程式內部,會自動在 Java 字串 (java.lang.String 型別) 和 Groovy 字串 (groovy.lang.GString) 兩者之間自動轉換,使用者不需煩惱這些細節。如下例:

    def name = "Michael"
    def greeting = "Hello ${name}"
    
    assert name instanceof java.lang.String
    assert greeting instanceof groovy.lang.GString

    陣列 (Array) vs. 串列 (List)

    在資料結構中,陣列 (array) 和連結串列 (linked list) 都是有序串列 (ordered list),但差別在於其內部實作。Groovy 的陣列和串列兩者從語法上看起來很像,實際上的差別在於其內部實作。

    Groovy 中的有序串列有三種:

    • 陣列 (array),不可變動大小
    • java.util.ArrayList,內部為動態陣列 (dynamic array),可變動大小
    • java.util.LinkedList,內部為雙向連結串列 (doubly-linked list),可變動大小

    這三者都是有序串列,為什麼要區分為三種實作呢?這主要是效率上的考量。陣列在隨機存取的效率好,但變動大小時效率較差;反之,串列在變動大小的效率好,隨機存取的效率則差。我們後文會再談陣列和串列的使用方式。

    映射 (Map)

    映射 (map) 是以鍵值對 (key-value pair) 為儲存單位的非線性資料結構。映射是相當實用的基礎資料結構,有些程式語言,像是 PHP 或 AWK,甚至只提供映射這類資料結構,再用映射去模擬陣列。我們後文會介紹映射。

    【分享本文】
    Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email
    【追蹤新文章】
    Facebook Twitter Plurk
    標籤: GROOVY, JAVA