基础语法

数据类型

和Java一样,有8种基础的内置类型

  • byte -表示字节值
  • short -表示一个短整型
  • int -表示整数
  • long -表示一个长整型
  • float -表示32位浮点数
  • double -表示64位浮点数
  • char -单个字符
  • boolean -表示一个布尔值,可以是true或false

注意,Groovy中会将这些基础类型转换成对象类型,也就是Java中的包装类,因此Groovy没有基本数据类型

int n = 0;
boolean b = false;
// 打印真实类型
println(n.class);
println(b.class);

输出:

class java.lang.Integer
class java.lang.Boolean

变量声明

有三种方式声明变量

// 1. 声明静态类型变量
int x = 5;
int y = 6; 

// 打印
println(x); 
println(X); 

// 2. 声明动态类型变量
def name = "Joe"; 
println(name); 
name = 2017;
println(name)

// 3. 省略def关键字,等同动态类型变量
age = 20;
println(age);
age = "18";
println(age)

字符串

Groovy中提供了两种字符串类型,一种是对应Java中的字符串的String类型,另一种是可以使用插值表达式的GString类型。

共有四种方式声明字符串字面量

// 1. 单引号声明
def s1 = 'zhangsan';

// 2. 双引号声明
def s2 = "lisi";

// 3. 三引号声明
def s3 = """
line1   break
line2
""";

// 4. 正斜杠声明
def s4 = /hello/;

println(s1.class);
println(s2.class);
println(s3.class);
println(s4.class);

打印:

class java.lang.String
class java.lang.String
class java.lang.String
class java.lang.String

这四种声明方式的区别:

  • 单引号声明的字符串不能包含插值表达式
  • 双引号字符串可以包含插值表达式
  • 正斜杠声明基本等同双引号声明,可包含插值表达式,且可以支持多行
  • 三引号声明的字符串可以包含原始格式,例如换行符等,因此用于声明多行字符串

需要注意,Groovy中的GString类型并非主动声明,而是由编译器智能判断,当检测到包含插值表达式时,自动将String转为GString类型。

def str = "haha";

def s1 = 'zhangsan $str';

// 插值表达式。当包含一个表达式时,可以使用${},单个变量使用$即可
def s2 = "lisi $str";

println(s1)
println(s1.class);
println(s2);
println(s2.class);

打印:

zhangsan $str
class java.lang.String
lisi haha
class org.codehaus.groovy.runtime.GStringImpl

Groovy没有明确的字符类型(Characters)。但有三种方式来将字符串作为字符处理

char c1 = 'A'
println(c1 instanceof Character)

def c2 = 'B' as char
println(c2 instanceof Character)

def c3 = (char)'C'
println(c3 instanceof Character)

集合类

List

Groovy同样支持java.util.List类型

// 声明 List
def numbers = [1, 2, 3, 4, 5];
ArrayList arrayList = [1, "a", true];

// 使用索引访问
println(arrayList[0] == 1);
println(arrayList[1] == "a");

// 支持负数索引。负值表示从右向左index,-1为列表末尾的元素
println(arrayList[-1]);


// 支持切片,截取包含部分元素的子集(注意,切片操作亦适用于字符串)
// 1..3 表示截取索引值为 1<= index <3 的子集
println(numbers[1..3]);

// 添加元素
numbers.add(6);
// groovy提供的一种简便的添加操作
numbers << 7;

// 删除指定位置的元素
arrayList.remove(0);

// 新的列表迭代方式
numbers.each {println(it)};

注意:

  • 支持Java中List类的一些方法,同时Groovy还提供了一些新的语法
  • 使用切片时需注意,切片返回的是对原列表的引用而不是拷贝,这意味着修改切片将改变原列表

Map

Groovy中的Map是java.util.LinkedHashMap

// 声明一个Map
def colors = [red: '#FF0000', green: '#00FF00', blue: '#0000FF'];

// 两种访问数据的方式
println(colors["red"]);
println(colors."blue");

// 添加数据
colors['pink'] = '#FF00FF';

// 删除数据
colors.remove("green");


def name = 'zhangsan'

// 不能直接将变量作为键存放
def person = [name: 18]
println(person.containsKey(name))  // false

// 使用括号包裹键
def person2 = [(name): 18]
println(person2.containsKey(name)) // true

// Map的迭代
colors.each {entry->println("Key=${entry.key} Value=${entry.value}")}

函数与闭包

Groovy中既可以像Java一样面向对象编程,也可以像Python一样脚本化的面向过程编程。因此我们可以不需要main函数,,也不必声明一个类,可以直接在脚本中定义顶级函数,并从上往下执行代码。

// 两种定义函数的方式

// 1. 使用def关键字定义,不需声明返回值类型
def function1(int a,int b){
    println("$a,$b");
}

// 2. 不使用def,但要显示声明返回值类型
String function2(a,b){
    return "$a $b";
}

function1();

Groovy中还需要注意

  • 函数的形参可以省略类型声明
  • 函数的形参可以指定默认值
  • 函数还可以声明不定参
  • 函数可以省略return语句,默认最后一行表达式的值为返回值
  • 在最外层的函数调用中可以省略圆括号“()”
  • Groovy中可以省略语句结尾的分号,且在大部分脚本中都会省略
// 声明一个加法函数,并给形参设置默认值
def add(x=0,y=10){
    // 等价于 return x+y;
    x+y
}

// 调用add函数,省略圆括号以及分号(无参函数不能省略圆括号)
add 8
add 7,9

// 最外层的println函数可以省略圆括号
// 等价于 println(add(7,8));
println add(7,8)

// println add 7,8   错误!此时add不能省略圆括号,不是最外层调用

// 声明一个不定参的函数
def sayHi(String... args){
    // 使用传统for循环遍历不定参
    for (int i = 0;i < args.size(); i++) {
        println("Hi,${args[i]} !")
    }  
}
// 传入不定参
sayHi "Alice","Bob","Alex","Bruce","Tom"

闭包

闭包是Groovy语言的重中之重,一定要熟练掌握。根据编程语言的一般通用概念,闭包通常指匿名函数和Lamda表达式,然而Groovy中对闭包的定义则更宽松,一般指花括号括起来的一段代码块。Groovy中闭包的写法也较为随意和宽松,对初学者理解阅读起来容易产生一定困扰。

闭包的一般格式:

{ [形参 -> ] 语句 }

这里使用"[]"包裹的部分是表示可选的,不是必须的,通常情况下都会省略。它相当于函数的形参列表,使用->符号将形参与闭包的语句间隔起来

// 使用静态类型声明一个闭包变量
Closure callback = { param -> println "param=$param" }

// 调用闭包的两种方式
// 1. 通过call方法调用
callback.call("name")

// 2. 直接调用
callback(88)

// 简化形式声明一个闭包,通常会省略参数和“->”符
def func = {println "param=$it"}
func("hello")

需要注意,闭包仅包含一个参数时,可以使用上述的简化形式声明。当一个闭包没有显式定义一个参数列表时,闭包总是有一个隐式的it参数,上例中等价于{it -> println "param=$it"}

如果你想声明一个不接受任何参数的闭包,且限定为不接受参数的调用,那么就必须显式声明一个空的参数列表,这样闭包内就不会包含隐式参数it

def hello = { -> println "hello" }

闭包作为函数参数

// 将闭包作为函数形参
def calc(a,b, closure){
    closure(a,b)
}

// 传入一个做加法的闭包
calc(8,10,{
    a,b-> println a + b
})

使用闭包时需要注意:

  1. 当函数有多个参数时,通常将闭包定义到最后一个参数的位置
  2. 闭包的形参也支持不定参
  3. 闭包通常有一种怪异的省略调用写法,在DSL中是一种主要用法,必须熟悉

以下省略调用,等同于上例中的calc调用

// 闭包的省略调用
// 当闭包位于函数最后一个参数时,可以将闭包提取到函数圆括号的外面进行调用
// 这种调用方式,好似将闭包挂载到函数上进行调用
calc (8,10) {
    a,b-> println a + b
}

前面讲了,当函数调用处于最外层时,还可以省略圆括号,因此还有以下写法

calc 8,10,{
    a,b-> println a + b
}

// 等价于以下形式去除括号
calc(8,10,{
    a,b-> println a + b
})

以下写法需特别注意,极易与函数声明混淆

// 声明只有一个闭包做形参的函数
def greet(closure){
    closure()
}

// 闭包省略调用
greet(){println 'hello!'}

// 省略括号调用闭包
greet{println 'hello!'}

关于Groovy的API的具体指南,可查看Groovy API文档


公众号“编程之路从0到1”

20190301102949549

Copyright © Arcticfox 2021 all right reserved,powered by Gitbook文档修订于: 2022-05-01 12:20:20

results matching ""

    No results matching ""