位元詩人 [Groovy] 程式設計教學:資料型態 (Data Type)

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

前言

資料型態 (data type) 用來規範資料在電腦程式中所占的記憶體大小和合法的 (valid) 操作。例如,數字型態資料可以加減乘除,布林型態資料可進行邏輯運算等。本文介紹 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 的資料型態,本節列出 Groovy 的內建資料型態。

基本型態 (Primitive Data Type)

以下是常用的基本型態 (base type):

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

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

參考型態 (Reference Data Type)

此外,常見的參考型態如下:

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

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

用類別建立資料型態

除了使用現有的類別,Groovy 可以用物件系統建立新的資料型態。Groovy 沿用 Java 的物件系統,並加上 Groovy 的改良。

布林 (Boolean)

布林型態用來表達數學上的布林運算,包括 truefalse 兩種值,用來表示邏輯上的真與假。

不過,重要的是知道那些值會判定為 false,這類值稱為 falsy value。如下:

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

除了 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 MainProgram
{
    public static void main(String[] args) {
        String name = "Michelle";

        // String concatenation
        System.out.println("Hello " + name);
    }
}

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

def name = "Michelle"

println "Hello ${name}"

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

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

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

def name = "Michelle"

assert 'Hello ${name}' == 'Hello ${name}'
assert "Hello ${name}" == 'Hello Michelle'

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

def name = "Michelle 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 = "Michelle"
def greeting = "Hello ${name}"

assert name instanceof java.lang.String
assert greeting instanceof groovy.lang.GString

陣列 (Array) 和串列 (List)

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

Groovy 中的有序串列有兩種:

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

映射 (Map)

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

關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。