Groovy系列(3)- Groovy基礎語法
Groovy基礎語法
動態型別
Groovy定義變數時:可以用Groovy風格的def宣告,不指定型別;也可以相容Java風格,指定變數型別;甚至還可以省略def或型別
def t1 = 't1' String t2 = 't2' t3 = 't3'
Groovy風格定義的變數型別是動態的,編譯成class時會自動轉換成正確的Java型別
def var = 'text' println var var = 5 println var + 1
可用Java實現類似效果如下
Object o = "text"; System.out.println(String.valueOf(o)); o= 5; System.out.println(String.valueOf(Integer.valueOf(o) + 1));
字串
Groovy支援靈活的字串語法,例如:
// 單引號字串 def a = 'hello "world"' // 雙引號字串 def b = "What's the weather like?" // 用加號連線字串,用等號對比字串 assert 'ab' == 'a' + 'b' // 三個單引號字串,支援直接換行 def aMultilineString = '''line one line two line three''' // 斜線字串中,反斜線不需要轉義,常用於正則表示式def fooPattern = /.*foo.*/ // 雙引號字串支援用$嵌入變數 def name = 'Tom' def greeting = "Hello ${name}" // 如需函式呼叫,則$後表示式要加大括號 def pi = 3.14 def piString = "Pi = ${pi.toString()}"
閉包 (Closure)
- 閉包是一個變數,又是一個函式,類似C語言中的函式指標,或者Java中只有一個方法的介面(Runnable等)
- 反編譯class檔案可以看出,Groovy閉包都會轉化為繼承groovy.lang.Closure的類
- 閉包方法的引數用箭頭定義,如果不特殊指定,則預設有一個it引數
- 閉包方法的返回值可以用return顯示指定,如果不指定則使用最後一條語句的值
def c1 = { println 'hello' } def c2 = { a, b -> println a println b } def c3 = { int a, String b -> println a println b } def c4 = { -> println 'hello' } def c5 = { println it } def c6 = { return it + 1 } def c7 = { it + 1 }
閉包呼叫可以用call,也可以直接像Java方法一樣加括號呼叫。
def c = { println it } c.call('text1') c('text2')
Java實現閉包效果:
abstract class MyClosure { abstract void call(Object o); } MyClosure c = new MyClosure() { @Override void call(Object o) { System.out.println(String.valueOf(o)); } }; c.call("text");
方法/閉包的定義與呼叫
Groovy中定義方法既可以用Groovy閉包風格,也可以用Java風格,引數/返回值型別也是可選的
def f1 = { text -> println text } def f2(text) { println text } void f3(String text) { println text }
注意函式定義不能這麼寫,會被視為函式呼叫
f4(text) {
println text
}
呼叫帶引數的閉包/函式,通常可以省略括號,如果最後一個引數是閉包,還可以單獨寫在括號後面,如下:
println('hello') println 'hello' def func = { text, Closure closure -> println text closure.call() } func('1', { println '2' }) func '3', { println '4' } func('5') { println '6' }
delegate,owner,this
檢視Closure類的原始碼,可以發現閉包中有delegate、owner、this三個成員變數,呼叫閉包沒有的屬性/方法時,會嘗試在這三個變數上呼叫。一般情況下:
this
指向閉包外部的Object,指定義閉包的類。
owner
指向閉包外部的Object/Closure,指直接包含閉包的類或閉包。
delegate
預設和owner一致,指用於處理閉包屬性/方法呼叫的第三方物件,可以修改。
在閉包構造時this和owner就已經確定並傳入,是隻讀的。如果需要修改,可以用Closure.rehydrate()方法克隆新的閉包,同時設定其this和owner。
Closure還有一個resolveStrategy屬性,有多種值(OWNER_FIRST、DELEGATE_FIRST、OWNER_ONLY、DELEGATE_ONLY、TO_SELF),預設為OWNER_FIRST,表示呼叫閉包沒有定義的屬性/方法時,先嚐試從owner取,再嘗試從delegate取。
Groovy程式碼示例:
class MyDelegate { def func = { println('hello') } } def c = { func() } c.delegate = new MyDelegate() c.call()
用Java實現類似效果如下:
static boolean callMethod(Object o, String method, Object... args) { try { Method func = o.getClass().getDeclaredMethod(method); if (func != null) { func.invoke(o, args); return true; } } catch (Exception ignored) { } return false; } class MyDelegate { void func() { System.out.println("func"); } } abstract class MyClosure { Object delegate; abstract void call(); } MyClosure c = new MyClosure() { @Override void call() { if (!callMethod(this, "func")) { callMethod(delegate, "func"); } } }; c.delegate = new MyDelegate(); c.call();
屬性與Getter、Setter
Groovy中物件的屬性(通常即成員變數)可以直接用名字訪問,實際上會呼叫getter和setter// File沒有absolutePath的成員變數,但有getAbsolutePath方法,可以直接當屬性訪問
println new File('text').absolutePath // File沒有setAbsolutePath方法,這句會報ReadOnlyPropertyException new File('text').absolutePath = '1'