【语言热身】Groovy 基础
刷题几乎不会用到 Groovy,本文目的仅在于快速熟悉 Groovy 语言,并了解其与 Java 语言的区别。
Groovy 简介
Groovy 是一门基于 JVM 的脚本语言。它在兼容 Java 语法的同时,借鉴了 Ruby、Python 等语言的特性,有自己一套简洁而灵活的语法。同时,运行在 JVM 上也意味着它也可以使用 Java 语言编写的库。这两点结合,让 Groovy 极其适合编写 Java 代码的测试脚本。
Groovy 兼容 Java 的语法。有关 Java 语法详见:站内文章【语言热身】Java 基础(热身索引)
Groovy 提供了大量的语法糖来方便我们编写脚本。
在 IDEA 中,可以通过 Tools->Groovy Console 随时随地进行简单 Groovy 的编写与调试。也可以另外创建 Groovy 项目。
缺点:
- 效率问题。Groovy 作为运行在 JVM 上的动态语言,运行效率是低于 Java 的。虽然可以用
@CompileStatic
注解来静态编译一些类以提高效率,但这样又会失去 Groovy 的一些动态语言的特性。 - 语法过于灵活,运用不当会降低可读性与可维护性。Groovy 支持元编程特性,可以在运行时动态添加方法。这一点自然可以简化代码,但也有很大的可能会降低可维护性。函数式编程与大量的语法糖会让不熟悉 Groovy 的人读起来一头雾水,反而降低了可读性。
main 方法
🍬 优化了 Java 的 main 方法。类似 Python。
main 方法的写法可以和 Java 相同。
1 | // Java 写法 |
Groovy 中 main 方法不一定要写在类中。
1 | // 执行 main 方法可以选其一执行 |
甚至,main 方法根本就不需要:
1 | // 分号 ; 是可选的 |
变量的定义和交换
🍬 简化 Java 多变量定义即交换方法。类似 Python。
1 | def (var1, var2) = [1, 2] |
数据类型
字符串
🍬 弥补了 Java 字符串的重复操作。类似 Python。
字符串操作:
+
:字符串链接*
:字符串重复str.length()
:字符串长度
可选类型
🍬 优化了 Java 的类型创建。类似 Python。
Groovy 是一种 " 可选 " 类型的语言,在理解该语言的基础知识时,这种区别很重要。 与 Java 相比,Java 是一种 " 强 " 类型语言,编译器知道每个变量的所有类型,并且可以在编译时理解和遵守合同。 这意味着可以在编译时确定方法调用。
在 Groovy 中编写代码时,开发人员可以灵活地提供或不提供类型。 这可以在实现中提供一些简单性,并且如果使用得当,可以以健壮和动态的方式为您的应用程序提供服务。
范围 Range
范围是指定值序列的简写。 Range 由序列中的第一个值和最后一个值表示,Range 可以是包含的,也可以是排除的。 包含范围包括从第一个到最后一个的所有值,而排他范围包括除最后一个之外的所有值。
1 | 1..10 // 包含范围的示例 |
1 | def range = 0..5 |
常用方法:
range.contains(e)
检查范围是否包含特定值e
range.get(i)
返回此 Range 中指定位置i
的元素。range.getFrom()
获取此 Range 的下限值。range.getTo()
获取此 Range 的上限值。range.isReverse()
是否为反转的 Rangerange.size()
返回此 Range 中的元素数。range.subList(fromIndex,toIndex)
:返回此 Range 在指定fromIndex
(包括)和toIndex
(不包括)之间部分的视图
列表 List
🍬 优化了 Java 中的 List 的创建。类似 Python。
Groovy 可以很轻松的定义 Java 中的 List
。
在 Groovy 中,List 列表包含一系列对象引用。 List 列表中的对象引用在序列中占据一个位置,并通过整数索引进行区分。 List 列表字面量表示为一系列用逗号分隔并用方括号括起来的对象。
1 | [11, 12, 13, 14] // 整数值列表 |
方法 | 描述 | Java 中类似方法 |
---|---|---|
add(e) |
将新值附加到此列表的末尾。 | Collection 的「增」 |
remove(i) |
删除此列表中指定位置的元素。 | ArrayList 的「删」 |
get(i) |
返回此列表中指定位置的元素。 | Collection 的「查」 |
contains(e) |
如果此 List 包含指定的值,则返回 true。 | Collection 的的判断 |
isEmpty() |
如果此 List 不包含任何元素,则返回 true | |
minus() |
创建一个由原始元素组成的新列表,而不是集合中指定的元素。 | |
plus() |
创建一个由原始元素和集合中指定的元素组成的新列表。 | |
pop() |
||
reverse() |
创建一个新的列表,它与原始列表的元素相反 | |
size() |
获取此 List 中的元素个数。 | Collection 获取长度 |
sort() |
返回原始列表的排序副本。 |
Java 集合相关内容详见:站内文章【语言热身】Java 集合的使用
通过范围可以快速定义 List
:
1 | def arrayList = 'A'..'D' as ArrayList |
List
的运算:
1 | def list1 = [] |
使用 Range
访问 List
:
1 | list = [1, 2, 3, 4, 5] |
Map
🍬 优化了 Java 中的 Map 的创建。
Groovy 可以很轻松的定义 Java 中的 Map
。
Map(也称为关联数组、字典、表和散列)是对象引用的无序集合。 Map 集合中的元素通过键值访问。 Map 中使用的键可以是任何类。 当我们插入 Map 集合时,需要键和值。
1 | ['TopicName' : 'Lists', 'Author' : 'Raghav'] // 以 TopicName 为键及其各自值的键值对集合。 |
方法 | 描述 | Java Map 存在类似方法 |
---|---|---|
containsKey(key) |
✅ | |
get(key) |
如果此 Map 中没有该键的条目,则返回 null 。 |
|
keySet() |
||
put(key,newValue) |
||
size() |
||
values() |
返回此 Map 中包含的值的集合视图。 | ❌ |
Java Map 集合相关内容详见:站内文章【语言热身】Java 集合的使用
正则表达式
🍬 优化了 Java 中正则包
java.util.regex
的使用。
1 | def regex = ~'Groovy' |
条件判断:
1 | def text = "some text to match" |
捕获组的获得:
1 | def pattern = ~/A is (\d+), B is (\d+)/ |
流程控制语句
Groovy 的 switch case 语法和 Java 类似,但是支持 List
、Range
、整数、数字、正则、闭包的判断。
可以使用 for in 语法:
1 | for (i in 1..10) |
方法
🍬 优化了 Java 中的方法声明,类似 Python。
方法可以接收任意数量的参数。 在定义参数时不需要显式定义类型。 可以添加诸如 public
、private
和 protected
等修饰符。 默认情况下,如果没有提供可见性修饰符,则该方法是公共的。
1 | def methodName() { |
Groovy 的方法定义中可以省略 return
关键字。
特殊方法
🍬 对常用方法的使用进行简化。
与 Ruby 类似,groovy 提供了 times
方法,让我们能写出更简洁的循环。
1 | 3.times { i -> print "$i " } |
在使用 Java 的时候,常常会遇到需要在同一个对象上多次调用方法。Groovy 也提供了相应的语法糖,这就是 with
方法。通过 with 方法,我们在调用对象方法时可以省略对象名。
1 | StringBuilder stringBuilder = new StringBuilder() |
调试(标准输出与字符串格式化)
🍬 优化了 Java 中的字符串格式化
字符串可以使用模板引擎。
各种类型直接 println
也能很好的展现出信息来。
1 | def num = 1 |
字符串的两端用单引号的话则不会进行格式化。
闭包与函数式编程
🍬 优化了 Java 中的 Stream 编程。
闭包是一个简短的匿名代码块。 它通常只跨越几行代码。 方法甚至可以将代码块作为参数。 它们本质上是匿名的。
与方法不同,闭包在被调用时总是返回一个值。
1 | // 形式 |
闭包的使用
闭包作为匿名代码块,可以像调用任何其他方法一样调用。
1 | // 定义一个不带参数的闭包 |
在 Groovy 中,闭包可以作为对象、参数和返回值,所以 Groovy 对高阶函数也有良好的支持。
1 | def addX = { int x -> |
闭包的参数
闭包的参数:
1 | def closureWithOneArg = { str -> str.toUpperCase() } |
当闭包没有显式定义形参列表 (使用 ->
) 时,闭包总是定义一个隐式形参,命名为 it
。
1 | def greeting = { it -> "Hello, $it!" } |
闭包可以像其他方法一样声明变量参数。如果最后一个形参是可变长度的 (或数组),就可以接受可变数量的实参:
1 | def concat1 = { String... args -> args.join('') } |
集合的筛选与遍历
一些集合提供了以闭包作为参数的方法,用于遍历集合。
1 | list.find({ it > 2 }) // 标准写法 |
一些方法:
each(closure)
:遍历集合,集合本身会改变,返回集合的引用。find(closure)
:在集合中找到第一个符合某个条件的值。该闭包必须是一些布尔表达式。findAll(closure)
:在接收对象中查找所有符合闭包条件的值。该闭包必须是一些布尔表达式。相当于对集合进行筛选。any(closure)
或every(closure)
:any
方法遍历集合的每个元素,检查布尔谓词是否对至少一个元素有效。返回一个布尔值。collect(closure)
:遍历一个集合,使用闭包作为转换器将每个元素转换为新值。
1 | // 示例 |
其他
在闭包中递归调用自身:
1 | def fibonacci = { int n -> |
面向对象
🍬 优化了 Java 中类的操作。
Groovy 会自动为类中的变量加上 getter 与 setter 。(没懂)
1 | class Person { |
Groovy 可以动态地给一个类或对象添加方法。
1 | class Cat { |
Json 的处理
JsonSlurper
:将 JSON 文本或阅读器内容解析为 Groovy 数据的类结构,例如映射、列表和原始类型,例如Integer
、Double
、Boolean
和String
。JsonOutput
:该方法负责将 Groovy 对象序列化为 JSON 字符串。
1 | import groovy.json.JsonOutput |
多线程
🍬 简化 Java 线程的创建
1 | Thread thr = Thread.start { |
文件读写
1 | def file = new File('test.txt') |