Groovy语法糖及常用用法
Groovy是JVM平台上的一种面向对象且同时支持静态动态的脚本语言,语法和Java区别不大,提供了一些语法糖,代码的表达能力更强。Gradle,Spring Cloud Contract等等都支持Groovy作为DSL(领域专用语言),同时Groovy在测试领域也有一席之地,因为语法简单,可以很快捷的编写Test Case。
语法糖
大致了解一些语法糖可以更舒服的看DSL
- 可以用def关键字定义变量和方法,编译期做类型推断
- 多变量同时创建
def (aa, bb) = [1, 2]- 范围创建
int[] range = 0..10;- 支持for in写法
for(variable in range) {
statement #1
statement #2
…
}- 方法参数支持默认值
def someMethod(parameter1, parameter2 = 0, parameter3 = 0) {
// Method code goes here
} - 字符串支持单引号和双引号,类似于shell,python,双引号中可识别变量
- 列表创建
List<String> strings = ["g", "r", "o", "o", "v", "y"]- map创建
Map<String, String> stringMap = ["name": "wang", "age": "99"]- 正则表达式,~后面直接跟正则语句,可直接用于判断
if ( "Groovy" =~ "^G")- trait关键字声明一个可以有属性和默认实现的接口,Java8之后的接口也都能达到同样效果
- 支持闭包,自己Call自己
def closure = { param -> println "Hello ${param}" };
closure.call("World");
10.times {num -> println num} - 函数科里化贼方便
def cl1 = {int a, b, c ->
a + b + c
}
def cl1Curry1 = cl1.curry(1)- 调用shell方便
println "ls -l".execute().text- instanceof可以简写成in
DSL
链式调用
在不产生歧义的情况下我们可以省略方法调用中的括号,使代码更像说话
// equivalent to: turn(left).then(right)
turn left then right
// equivalent to: take(2.pills).of(chloroquinine).after(6.hours)
take 2.pills of chloroquinine after 6.hours
// equivalent to: paint(wall).with(red, green).and(yellow)
paint wall with red, green and yellow
// with named parameters too
// equivalent to: check(that: margarita).tastes(good)
check that: margarita tastes good
// with closures as parameters
// equivalent to: given({}).when({}).then({})
given { } when { } then { }运算符重载
| Operator | Method |
|---|---|
| a + b | a.plus(b) |
| a - b | a.minus(b) |
| a * b | a.multiply(b) |
| a ** b | a.power(b) |
| a / b | a.div(b) |
| a % b | a.mod(b) |
| a & b | a.and(b) |
| a ^ b | a.xor(b) |
| a++ 或 ++a | a.next() |
| a– 或 –a | a.previous() |
| a[b] | a.getAt(b) |
| a[b] = c | a.putAt(b, c) |
| a << b | a.leftShift(b) |
| a >> b | a.rightShift(b) |
| a >>> b | a.rightShiftUnsigned(b) |
| switch(a) { case(b) : } | b.isCase(a) |
| if(a) | a.asBoolean() |
| ~a | a.bitwiseNegate() |
| -a | a.negative() |
| +a | a.positive() |
| a as b | a.asType(b) |
| a == b | a.equals(b) |
| a != b | ! a.equals(b) |
| a <=> b | a.compareTo(b) |
| a > b | a.compareTo(b) > 0 |
| a >= b | a.compareTo(b) >= 0 |
| a < b | a.compareTo(b) < 0 |
| a <= b | a.compareTo(b) <= 0 |
脚本基类
我们运行的Groovy脚本在编译过程中都自动继承了 groovy.lang.Script 这个抽象类,并把脚步内容绑定到run方法中执行。
可以通过创建一个Binding在脚本和基类中创建公用的变量
def binding = new Binding()
def shell = new GroovyShell(binding)
binding.setVariable('x',1)
binding.setVariable('y',3)
shell.evaluate 'z=2*x+y'
assert binding.getVariable('z') == 5 可以自定义基类
class BaseScript extends Script{
String name
public void greet() { println "Hello, $name!" }
@Override
Object run() {
greet()
}
}
@BaseScript demo.BaseScript baseScript
setName "100"
greet()@DelegatesTo
是一个文档与编译时注释,当我们使用了委托模式去执行闭包时,文档生成,IDE以及类型推断都无法准确知道闭包具体被委托到哪里执行,我们就需要使用此注解显示声明。
当我们要实现如下效果时,我们需要定义一个email方法接受一个闭包,然后通过构建模式创建一个EmailSpec,去初始化并且委托执行闭包
email {
from 'dsl-guru@mycompany.com'
to 'john.doe@waitaminute.com'
subject 'The pope has resigned!'
body {
p 'Really, the pope has resigned!'
}
}
def email(@DelegatesTo(strategy=Closure.DELEGATE_ONLY, value=EmailSpec) Closure cl) {
// ...
}当我们要委托给方法的另一个参数时可以
def exec(@DelegatesTo.Target Object target, @DelegatesTo Closure code) {
// rehydrate方法创建一个闭包副本
def clone = code.rehydrate(target, this, this)
clone()
}自定义编译器
增加默认导入,并且支持别名
import org.codehaus.groovy.control.customizers.ImportCustomizer
def icz = new ImportCustomizer()
// "normal" import
icz.addImports('java.util.concurrent.atomic.AtomicInteger', 'java.util.concurrent.ConcurrentHashMap')
// "aliases" import
icz.addImport('CHM', 'java.util.concurrent.ConcurrentHashMap')
// "static" import
icz.addStaticImport('java.lang.Math', 'PI') // import static java.lang.Math.PI
// "aliased static" import
icz.addStaticImport('pi', 'java.lang.Math', 'PI') // import static java.lang.Math.PI as pi
// "star" import
icz.addStarImports 'java.util.concurrent' // import java.util.concurrent.*
// "static star" import
icz.addStaticStars 'java.lang.Math' // import static java.lang.Math.*可用于限制AST的级别,比如使用者不能用闭包,不允许导入其他包等等
构建
Groovy内置了很多好用的构建器,具体使用查看官方教程
Groovy语法糖及常用用法
https://note.0moe.cn/Java/2021/04/10/Groovy语法糖及常用用法/