Groovy 3 亮点
作者:Paul King
发布时间:2020年2月13日 上午2:28
一般改进
Groovy 既具有动态特性(支持类似于 Ruby 和 Python 的代码风格),也具有静态特性(支持类似于 Java、Kotlin 和 Scala 的风格)。Groovy 继续改进这两种特性 - 填补任何功能空白。例如,Groovy 有许多更好的管理空值的工具。您可以使用 Groovy 的空安全导航运算符,借助 Java 的 Optional
或为类型检查器提供空检查扩展。在 Groovy 3 中,这些功能得到了增强,增加了对数组、列表和映射的空安全索引,以及一个新的 AST 转换 @NullCheck
,用于自动为代码添加空检查。
总的来说,该语言设计很大程度上借鉴了 Java,因此我们会密切关注 Java 的变化,并在适当时采取相应的行动。为了让 Groovy 为 Java 模块做好准备,并使其与 JDK 9-15 版本良好配合,我们做了很多工作。其他工作则大幅提高了字节码生成的性能,它利用了 JVM 调用动态功能。Groovy 4 中已经在进行进一步改进这些领域的更改。
在底层还有许多其他性能改进。编译期间的类型解析效率更高,并且为许多场景生成了更高效的字节码。Maven BOM 的添加允许从其他项目更灵活地使用 Groovy。
Groovy 在脚本、测试、编写领域特定语言 (DSL) 以及金融计算和数据科学等领域也具有独特的优势。我们一直在努力确保这些优势得到保持。用于高精度数字的精度得到了提高,并且是可配置的。Groovy 控制台和 groovysh 等许多工具也得到了改进。
Groovy 的其他关键优势,如其运行时和编译时元编程功能,也进行了许多小的增强。总而言之,此版本代表了几年来工作成果的结晶。自 Groovy 2.5 以来,已经添加了 500 多个新功能、改进和错误修复。下面只讨论一些亮点。
Parrot 解析器
Groovy 有了一个新的解析器。虽然这主要是 Groovy 内部的一个变化,但对用户来说,好消息是新的解析器更加灵活,如果需要,可以更快地更改语言。
新语法
新的解析器为我们提供了一个添加一些新语法特性的机会
-
!in 和 !instanceof 运算符
assert 45 !instanceof Date assert 4 !in [1, 3, 5, 7]
-
Elvis 赋值运算符
def first = 'Jane' def last = null first ?= 'John' last ?= 'Doe' assert [first, last] == ['Jane', 'Doe']
-
身份比较运算符
assert cat === copyCat // operator shorthand for "is" method assert cat !== lion // negated operator shorthand
-
安全索引(用于映射、列表和数组)
println map?['someKey'] // return null if map is null instead of throwing NPE
Java 兼容性
Groovy 语法可以被认为是 Java 语法的超集。在适当的时候使用 Groovy 提供的增强功能被认为是一种良好的风格,但 Groovy 的目标是仍然尽可能多地支持 Java 语法,以便于从 Java 迁移或方便同时使用 Java 和 Groovy 的人员进行切换。
新的解析器提供的灵活性使得可以填补几个语法兼容性漏洞,包括
-
do/while 循环
def count = 5 def factorial = 1 do { factorial *= count-- } while(count > 1) assert factorial == 120
-
增强的经典 Java 风格 for 循环(参见多赋值 for 循环示例;请注意 for 语句最后一个子句中的逗号)
-
与 for 循环结合使用的多赋值
def count = 3 println 'The next three months are:' for (def (era, yr, mo) = new Date(); count--; yr = mo == 11 ? yr + 1 : yr, mo = mo == 11 ? 0 : mo + 1) { println "$yr/$mo" }
-
Java 风格的数组初始化(但您可能更喜欢 Groovy 的字面量列表表示法)
def primes = new int[] {2, 3, 5, 7, 11}
-
Lambda 表达式(但您可能经常更喜欢 Groovy 的闭包,它支持蹦床/尾递归、部分应用/柯里化、记忆化/自动缓存)
(1..10).forEach(e -> { println e })
assert (1..10).stream() .filter(e -> e % 2 == 0) .map(e -> e * 2) .toList() == [4, 8, 12, 16, 20]
def add = (int x, int y) -> { def z = y; return x + z } assert add(3, 4) == 7
-
方法引用(但您可能经常更喜欢 Groovy 的方法指针,它是具有前面提到的优点的闭包)
assert ['1', '2', '3'] == Stream.of(1, 2, 3) .map(String::valueOf) .toList()
-
“var”保留类型(即使使用 JDK 8 也允许使用 Java 10/11 功能)
var two = 2 // Java 10 IntFunction<Integer> twice = (final var x) -> x * two // Java 11 assert [1, 2, 3].collect{ twice.apply(it) } == [2, 4, 6]
-
ARM Try with resources(Java 7 和 9 变体在 JDK 8 上工作 - 但您可能更喜欢 Groovy 用于资源的内部迭代方法)
def file = new File('/path/to/file.ext') def reader = file.newReader() try(reader) { String line = null while (line = reader.readLine()) { println line } }
-
嵌套代码块
-
Java 风格的非静态内部类实例化
-
接口默认方法(但您可能更喜欢 Groovy 的特性)
interface Greetable { String target() default String salutation() { 'Greetings' } default String greet() { "${salutation()}, ${target()}" } }
拆分包更改
为了使 Groovy 的模块化 jar 成为一流的模块,几个类已经移动了包。一些例子
groovy.util.XmlParser => groovy.xml.XmlParser
groovy.util.XmlSlurper => groovy.xml.XmlSlurper
groovy.util.GroovyTestCase => groovy.test.GroovyTestCase
在大多数情况下,Groovy 3 中同时提供了旧类和新类。但在 Groovy 4 中,旧类将被删除。有关这些更改的完整列表,请参阅发行说明。
DGM 改进
Groovy 为现有的 Java 类添加了许多扩展方法。在 Groovy 3 中,添加了大约 80 个新的此类扩展方法。我们在这里只重点介绍几个
-
数组和可迭代对象上的
average()
assert 3 == [1, 2, 6].average()
-
String、CharSequence 和 GString 上的
takeBetween()
assert 'Groovy'.takeBetween( 'r', 'v' ) == 'oo'
-
数组和可迭代对象上的
shuffle()
和shuffled()
def orig = [1, 3, 5, 7] def mixed = orig.shuffled() assert mixed.size() == orig.size() assert mixed.toString() ==~ /\[(\d, ){3}\d\]/
-
Future 上的
collect{ }
Future<String> foobar = executor.submit{ "foobar" } Future<Integer> foobarSize = foobar.collect{ it.size() } // async assert foobarSize.get() == 6
-
LocalDate 上的
minus()
def xmas = LocalDate.of(2019, Month.DECEMBER, 25) def newYear = LocalDate.of(2020, Month.JANUARY, 1) assert newYear - xmas == 7 // a week apart
其他改进
改进的注解支持
最新版本的 Java 允许在更多地方使用注解 (JSR308)。Groovy 现在也支持此类用例。这对 Spock、Micronaut、Grails、Jqwik 等框架以及其他框架非常重要,并且为其他 AST 转换(Groovy 的一个关键元编程特性)打开了大门。
Groovydoc 增强
除了 Groovydoc 支持新的解析器外,您现在还可以通过各种方式嵌入 Groovydoc 注释
-
可以将它们放在 AST 中,供 AST 转换和其他工具使用。
-
以特殊
/**@
开头注释分隔符开头的 Groovydoc 注释也可以嵌入到类文件中。这提供了一个在 Groovy 中的功能,其灵感来自于 Ruby 等语言,这些语言可以将文档嵌入到标准二进制 jar 中,因此始终可用,而无需依赖于单独的 javadoc jar。
获取 Groovy
官方源代码版本在下载页面上。您可以在该页面上找到便捷的二进制文件、可下载的文档、SDK 包以及指向各种社区工件的指针,以及允许您验证安装的信息。您可以在任何支持 Java 的平台上使用 zip 安装,或者考虑使用适合您平台或 IDE 的安装程序。
最新版本 Groovy 3 的 Windows 安装程序可在bintray上找到。(社区工件)
对于 Linux 用户,最新版本的 Groovy 3 也可在Snap Store中找到。(社区工件)
对于 Eclipse 用户,最新版本的 Groovy 3 groovy-eclipse-batch 插件可在bintray上找到。(社区工件)
对于 Intellij 用户,最新社区版本的IDEA支持 Groovy 3。