【在主画面加入捷径】
       
【选择语系】
繁中 简中

[Groovy] 程序设计教学:数据类型 (Data Type)

【赞助商连结】

    数据类型 (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,甚至只提供映射这类数据结构,再用映射去仿真数组。我们后文会介绍映射。

    【赞助商连结】
    TAGS: GROOVY, JAVA