java and dsl_Groovy语法糖以及DSL
前言
Why
初次接觸到Groovy是在實習中接觸到一個 純Groovy寫的項目,當時看了下這不就是沒有分號的Java么,而且也是有年紀的語言了,并不想投入時間學習。后來工作中越來越多的看到Groovy的身影,Gradle,Spring Cloud Contract等等都支持Groovy作為DSL(領域專用語言),同時Groovy在測試領域也有一席之地,因為語法簡單,可以很快捷的編寫Test Case,總之可以把Groovy看作Java的小伙伴,好幫手。
What
Groovy是JVM平臺上的一種面向對象且同時支持靜態動態的腳本語言,語法和Java區別不大,提供了一些語法糖,代碼的表達能力更強。默認小伙伴們都已經有了Java基礎,本文主要介紹Groovy比Java多出的語法糖,以及使用較多的DSL。
語法糖
大致了解一些語法糖可以更舒服的看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 strings = ["g", "r", "o", "o", "v", "y"]
map創建
Map 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.or(b)
a & b
a.and(b)
a ^ b
a.xor(b)
a++ or ++a
a.next()
a-- or --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內置了很多好用的構建器,具體使用查看官方教程
[官方教程](
總結
以上是生活随笔為你收集整理的java and dsl_Groovy语法糖以及DSL的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php抽象方法db,PHP笔记之抽象方法
- 下一篇: reducebykeyandwindow