Groovy 4.0:这10个新功能使它变得很棒!

切换表达式

与Java相比,Groovy一直具有更强大的switch语句。类案例值、正则表达式案例值、集合案例值、闭包案例值,或在末尾,相等值案例。所有这些选项使Switch声明成为Groovy世界中的一等公民。现在,随着Java编程语言的最新更新,Groovy还支持switch表达式。switch 语句和 switch 表达式之间的主要区别在于,后者引入了与 Java 兼容的语法并返回值。您仍然可以使用各种组合作为案例,但新语法将使代码更加优雅。

switch (value) {
    case null -> 'just a null'
    case 0 -> 'zero'
    case 1 -> 'one'
    case { it instanceof List && it.empty } -> 'an empty list'
    case List -> 'a list'
    case '007' -> 'James Bond'
    case ~/\d+/ -> 'a number'
    default -> 'unknown'
}

记录

记录是一种方便的不可变“数据载体”类型,在Java 16中引入。现在,它们也可以在Groovy中使用。相同的语法,尽管Groovy还引入了一个可以互换使用的“”注释。即使这不像Java那样改变了游戏规则,但很高兴看到Groovy在其母语中引入了最新功能。@RecordType

record Point(int x, int y) {}

def p1 = new Point(0, 0)
def p2 = new Point(2, 4)
def p3 = new Point(0, 0)

assert p1.x() == 0
assert p1.y() == 0
assert p2.x() == 2
assert p2.y() == 4
assert p1.toString() == 'Point[x=0, y=0]'
assert p2.toString() == 'Point[x=2, y=4]'
assert p1 == p3

密封类型

另一个受 Java 编程语言最新变化影响的功能。密封类型允许您限制哪些类(或接口)可以扩展特定的密封类型。如果所有相关类都存储在同一源文件中,则可以显式(使用“allows”关键字)或隐式(不带任何关键字)完成此操作。与记录类似,Groovy还引入了注释,如果这是您的偏好,则可以互换使用。何时使用密封类型?也许出于安全原因,您不希望允许任何人扩展您的类。或者,您可能希望将来向接口添加新方法,并且希望严格控制受影响的子类。如果是这样的话 - 密封类型可能是您想要查看的内容。@Sealed

import groovy.transform.ToString

sealed interface Tree<T> { }

@Singleton
final class Empty implements Tree {
    String toString() { "Empty" }
}

@ToString
final class Node<T> implements Tree<T> {
    final T value
    final Tree<T> left, right

    Node(T value, Tree<T> left, Tree<T> right) {
        this.value = value
        this.left = left
        this.right = right
    }
}

类型检查器

尽管Groovy主要以其动态功能而闻名,但它允许您在类型检查方面比Java严格得多。新添加的“groovy-typecheckers”可选模块引入了一个正则表达式检查器,可以帮助您在编译时捕获正则表达式中的错误。就像在此示例中一样 - 我们有一个缺少右括号的正则表达式。通常,编译器无法检测到此类问题,因此我们可以在单元测试中或在运行时找到它。在这里,我在GroovyShell中运行此脚本,因此我可以捕获预期的MultiCompilationErrorsException。

import groovy.transform.TypeChecked

@TypeChecked(extensions = 'groovy.typecheckers.RegexChecker')
def testRegexChecker() {
    def date = '2022-04-03'

    assert date ==~ /(\d{4})-(\d{1,2})-(\d{1,2}/
}

内置宏方法

宏方法允许您访问和操作编译器 AST 数据结构。宏方法调用看起来像常规方法调用,但事实并非如此 - 它将在编译时被生成的代码替换。以下是此类宏方法的几个示例。例如,“SV”方法创建一个具有变量名称和关联值的字符串。“SVI”使用Groovy的conspect方法,该方法产生稍微不同的输出 - 例如,它不会像本例中所示展开范围对象。

def num = 42
def list = [1 ,2, 3]
def range = 0..5
def string = 'foo'

assert SV(num, list, range, string) == 'num=42, list=[1, 2, 3], range=[0, 1, 2, 3, 4, 5], string=foo'

assert SVI(range) == 'range=0..5'

assert NV(range) instanceof NamedValue

assert NV(string).name == 'string' && NV(string).val == 'foo'

@POJO注释

如果你熟悉Groovy,你已经知道每个Groovy类都实现了“GroovyObject”接口。如果您只在Groovy生态系统中保留代码,则无需担心。但有时,您希望使用Groovy编写一个库代码,该代码也可以在纯Java项目中使用。你可以将这两个世界与新的“@POJO”注释放在一起。任何带有''注释的类都可以使用,而无需在运行时添加Groovy。就像此示例中显示的“PojoPoint”类一样。让我们编译它并将其作为Java程序运行。@POJO

import groovy.transform.CompileStatic
import groovy.transform.Immutable
import groovy.transform.stc.POJO

@POJO
@Immutable
@CompileStatic
class PojoPoint {
    int x, y

    static void main(String[] args) {
        PojoPoint point = new PojoPoint(1,1)
        System.out.println(point.toString())
    }
}

Groovy 合同

如果您厌倦了编写防御性代码,那么时髦的合同可能是一种祝福。'' 类批注定义在对象的生存期内(构造函数调用之后、方法调用之前和之后)检查的断言。'' 注释表示方法前提条件 - 在方法调用之前执行的断言。''注释用作方法后置条件 - 在方法调用后执行的断言。有些人可能会说,这些注释可以很容易地被方法主体中的显式断言所取代。这是真的。但是,如果你想保持合同和业务逻辑很好地分开,那么Groovy合同听起来是一个很好的起点。@Invariant@Requires@Ensures

import groovy.contracts.Ensures
import groovy.contracts.Invariant
import groovy.contracts.Requires

@Invariant({ speed >= 0 })
class Rocket {
    int speed = 0
    boolean started = false

    @Requires({ !started })
    Rocket startEngine() { tap {started = true }}

    @Requires({ started })
    Rocket stopEngine() { tap { started = false }}

    @Requires({ started })
    @Ensures({ old.speed < speed })
    Rocket accelerate(int value) { tap { speed += value }}
}

金克

时髦集成查询语言。如果你是类似SQL语言的粉丝,你会喜欢这个功能。GINQ 允许您使用类似 SQL 的语法查询集合。就像这个例子一样。我们有一个包含“人员”字段的 JSON 文档。我们使用 GINQ 按降序查找所有 18 岁以上的人,获取前三个结果,并将返回的数据修改为大写,并限制为仅前两个字母。据我所知,Groovy团队计划扩展GINQ以支持SQL数据库,以便您可以编写编译时生成和类型检查的SQL查询。

import groovy.json.JsonSlurper

def json = new JsonSlurper().parseText '''
    {
        "people": [
            {"name": "Alan", "age": 11},
            {"name": "Mary", "age": 26},
            {"name": "Eric", "age": 34},
            {"name": "Elisabeth", "age": 14},
            {"name": "Marc", "age": 2},
            {"name": "Robert", "age": 52},
            {"name": "Veronica", "age": 32},
            {"name": "Alex", "age": 17}
        ]
    }
    '''

assert GQ {
    from f in json.people
    where f.age >= 18
    orderby f.age in desc
    limit 3
    select f.name.toUpperCase().take(2)

}.toList() == ['RO', 'ER', 'VE']

TOML 支持

Groovy 3添加了YAML格式支持,现在Groovy 4也增加了TOML格式支持。如果您在代码库中使用此类格式,则非常有用。值得一提的是,TomlBuilder 类生成的输出不会生成表头,而是生成点分隔的字段名称。

import groovy.toml.TomlBuilder
import groovy.toml.TomlSlurper

String input = '''
# This is a TOML document (taken from https://toml.io)

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00

[database]
enabled = true
ports = [ 8000, 8001, 8002 ]
data = [ ["delta", "phi"], [3.14] ]
temp_targets = { cpu = 79.5, case = 72.0 }

[servers]

[servers.alpha]
ip = "10.0.0.1"
role = "frontend"

[servers.beta]
ip = "10.0.0.2"
role = "backend"
'''

def toml = new TomlSlurper().parseText(input)

assert toml.title == 'TOML Example'
assert toml.owner.name == 'Tom Preston-Werner'
assert toml.database.ports == [8000, 8001, 8002]
assert toml.servers.alpha.ip == '10.0.0.1'
assert toml.servers.beta.ip == '10.0.0.2'


TomlBuilder builder = new TomlBuilder()
builder {
    title 'This is TOML document'
    servers {
        alpha {
            ip '10.0.0.1'
        }
        beta {
            ip '10.0.0.2'
        }
    }
}
assert builder.toString() ==
'''title = 'This is TOML document'
servers.alpha.ip = '10.0.0.1'
servers.beta.ip = '10.0.0.2'
'''

JDK 8 兼容性

运行Groovy 4所需的最低Java版本是JDK 8。你可能会问 - “但是Groovy如何处理,例如,记录”?让我把它展示给你们看。在这里,我有Java 17和Groovy 4.0.1。我将把这个脚本编译成类文件,当我们在IntelliJ中打开它时,我们可以看到它产生了一个Java原生记录,就像预期的那样。现在我要切换到Java 8,让我们做同样的事情。当我们在 IntelliJ 中打开类文件时,我们可以看到现在生成的类“模拟”记录行为,但不使用本机记录语法。这就是Groovy代码可移植性的美妙之处 - 相同的代码和全新的语言功能,即使使用相当旧的Java版本也可以使用。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值