Groovy 3 亮点
发布时间:2020-02-13 02:28AM
一般改进
Groovy 既有动态特性(支持类似于 Ruby 和 Python 的代码风格)也有静态特性(支持类似于 Java、Kotlin 和 Scala 的风格)。Groovy 持续改进这两种特性——填补任何功能空白。举一个例子,Groovy 提供了许多设施来更好地管理空值。你可以使用 Groovy 的空安全导航运算符,利用 Java 的 Optional
,或者为类型检查器提供一个空检查扩展。Groovy 3 通过数组、列表和映射的空安全索引以及一个新的 AST 转换 @NullCheck
增强了这些功能,用于自动对代码进行空检查。
总的来说,语言设计大量借鉴了 Java,因此会密切关注 Java 的变化并酌情采取相应行动。为了使 Groovy 为 Java 模块做好准备并使其与 JDK 9-15 版本良好配合,已经做了大量工作。其他工作显著提高了字节码生成的性能,该生成利用了 JVM 的 invoke dynamic 功能。在 Groovy 4 中,这些领域将进一步改进,目前正在进行额外的更改。
幕后还有许多其他性能改进。编译期间会进行更高效的类型解析,并且针对许多场景生成更高效的字节码。Maven BOM 的添加允许其他项目更灵活地使用 Groovy。
Groovy 在脚本、测试、编写领域特定语言 (DSL) 以及金融计算和数据科学等领域也具有独特的优势。我们一直在努力确保这些优势得以保持。高精度数字的准确性得到了提高并且可配置。Groovy Console 和 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 的 traits)
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 安装程序(社区工件)可从以下地址获取:https://groovy.jfrog.io/artifactory/dist-release-local/groovy-windows-installer/
对于 Linux 用户,最新版本的 Groovy 3 也可在 Snap Store 中获取。(社区工件)
对于 Eclipse 用户,最新版本的 Groovy 3 groovy-eclipse-batch 插件可从 bintray 获取(更新:现已在 Maven Central 上)。(社区工件)
对于 IntelliJ 用户,最新社区版的 IDEA 支持 Groovy 3。