Gradle從入門到實戰 - Groovy基礎
前言
如之前所描述,本公眾號的文章主要有如下幾個方向:
-
Android 方向:特定領域的Android技術實戰,幫助大家從根源上提高
-
AI(人工智慧)方向:幫助非AI工程師入門AI領域
-
外界投稿:主題不定,不定期推送
-
職場、生活等:推送時間不定,看心情
Android方向的第一期文章,會專注於Gradle系列,名字叫做『 Gradle從入門到實戰』,計劃有如下幾個課程:
-
Groovy基礎
-
全面理解Gradle
-
如何建立Gradle外掛
-
分析Android的build tools外掛
-
實戰,從0到1完成一款Gradle外掛
本篇文章講解Groovy基礎。為什麼是Groovy基礎呢,因為玩轉Gradle並不需要學習Groovy的全部細節。Groovy是一門jvm語言,功能比較強大,細節也很多,全部學習的話比較耗時,對我們來說收益較小。
為什麼是Gradle?
Gradle是目前Android主流的構建工具,不管你是通過命令列還是通過AndroidStudio來build,最終都是通過Gradle來實現的。所以學習Gradle非常重要。
目前國內對Android領域的探索已經越來越深,不少技術領域如外掛化、熱修復、構建系統等都對Gradle有迫切的需求,不懂Gradle將無法完成上述事情。所以Gradle必須要學習。
如何學習Gradle?
大部分人對Gradle表示一臉懵逼,每當遇到一個問題的時候都需要從網上去查,這是一個誤區。
Gradle不單單是一個配置指令碼,它的背後是幾門語言,如果硬讓我說,我認為是三門語言。
-
Groovy Language
-
Gradle DSL
-
Android DSL
DSL的全稱是Domain Specific Language,即領域特定語言,或者直接翻譯成“特定領域的語言”,算了,再直接點,其實就是這個語言不通用,只能用於特定的某個領域,俗稱“小語言”。因此DSL也是語言。
在你不懂這三門語言的情況下,你很難達到精通Gradle的程度。這個時候從網上搜索,或者自己記憶的一些配置,其實對你來說是很大的負擔。但是把它們當做語言來學習,則不需要記憶這些配置,因為語言都是有文件的,我們只需要學語法然後查文件即可,沒錯,這就是學習方法,這就是正道。
你需要做什麼呢?跟著我學習就行啦!下面步入正題,讓我們來開始學習Groovy的基本語法。
Groovy和Java的關係
Groovy是一門jvm語言,它最終是要編譯成class檔案然後在jvm上執行,所以Java語言的特性Groovy都支援,我們完全可以混寫Java和Groovy。
既然如此,那Groovy的優勢是什麼呢?簡單來說,Groovy提供了更加靈活簡單的語法,大量的語法糖以及閉包特性可以讓你用更少的程式碼來實現和Java同樣的功能。比如解析xml檔案,Groovy就非常方便,只需要幾行程式碼就能搞定,而如果用Java則需要幾十行程式碼。
Groovy的變數和方法宣告
在Groovy中,通過 def 關鍵字來宣告變數和方法,比如:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def a = 1;
def b = "hello world";
def int c = 1;
def hello() {
println ("hello world"); return 1;
}
</pre>
在Groovy中,很多東西都是可以省略的,比如
-
語句後面的分號是可以省略的
-
變數的型別和方法的返回值也是可以省略的
-
方法呼叫時,括號也是可以省略的
-
甚至語句中的return都是可以省略的
所以上面的程式碼也可以寫成如下形式:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def a = 1
def b = "hello world"
def int c = 1
def hello() {
println "hello world" // 方法呼叫省略括號 1;// 方法返回值省略return
}
def hello(String msg) {
println (msg)
}
// 方法省略引數型別
int hello(msg) {
println (msg) return 1
}
// 方法省略引數型別
int hello(msg) {
println msg return 1 // 這個return不能省略 println "done"
}
</pre>
總結
-
在Groovy中,型別是弱化的,所有的型別都可以動態推斷,但是Groovy仍然是強型別的語言,型別不匹配仍然會報錯;
-
在Groovy中很多東西都可以省略,所以尋找一種自己喜歡的寫法;
-
Groovy中的註釋和Java中相同。
Groovy的資料型別
在Groovy中,資料型別有:
-
Java中的基本資料型別
-
Java中的物件
-
Closure(閉包)
-
加強的List、Map等集合型別
-
加強的File、Stream等IO型別
型別可以顯示宣告,也可以用 def 來宣告,用 def 宣告的型別Groovy將會進行型別推斷。
基本資料型別和物件這裡不再多說,和Java中的一致,只不過在Gradle中,物件預設的修飾符為public。下面主要說下String、閉包、集合和IO等。
1. String
String的特色在於字串的拼接,比如
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def a = 1
def b = "hello"
def c = "a= {b}"
println c
outputs:
a=1, b=hello
</pre>
2. 閉包
Groovy中有一種特殊的型別,叫做Closure,翻譯過來就是閉包,這是一種類似於C語言中函式指標的東西。閉包用起來非常方便,在Groovy中,閉包作為一種特殊的資料型別而存在,閉包可以作為方法的引數和返回值,也可以作為一個變數而存在。
如何宣告閉包?
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
{ parameters ->
code
}
</pre>
閉包可以有返回值和引數,當然也可以沒有。下面是幾個具體的例子:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def closure = { int a, String b ->
println "a=${a}, b=${b}, I am a closure!"
}
// 這裡省略了閉包的引數型別
def test = { a, b ->
println "a=${a}, b=${b}, I am a closure!"
}
def ryg = { a, b ->
a + b
}
closure(100, "renyugang")
test.call(100, 200)
def c = ryg(100,200)
println c
</pre>
閉包可以當做函式一樣使用,在上面的例子中,將會得到如下輸出:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
a=100, b=renyugang, I am a closure!
a=100, b=200, I am a closure!
300
</pre>
另外,如果閉包不指定引數,那麼它會有一個隱含的引數 it
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
// 這裡省略了閉包的引數型別
def test = {
println "find ${it}, I am a closure!"
}
test(100)
outputs:
find 100, I am a closure!
</pre>
閉包的一個難題是如何確定閉包的引數,尤其當我們呼叫Groovy的API時,這個時候沒有其他辦法,只有查詢Groovy的文件:
http://www.groovy-lang.org/api.html
http://docs.groovy-lang.org/latest/html/groovy-jdk/index-all.html
下面會結合具體的例子來說明如何查文件。
3. List和Map
Groovy加強了Java中的集合類,比如List、Map、Set等。
List的使用如下:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def emptyList = []
def test = [100, "hello", true]
test[1] = "world"
println test[0]
println test[1]
test << 200
println test.size
outputs:
100
world
4
</pre>
List還有一種看起來很奇怪的操作符<<,其實這並沒有什麼大不了,左移位表示向List中新增新元素的意思,這一點從文件當也能查到。

image
其實Map也有左移操作,這如果不查文件,將會非常費解。
Map的使用如下:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def emptyMap = [:]
def test = ["id":1, "name":"renyugang", "isMale":true]
test["id"] = 2
test.id = 900
println test.id
println test.isMale
outputs:
900
true
</pre>
可以看到,通過Groovy來操作List和Map顯然比Java簡單的多。
這裡藉助Map再講述下如何確定閉包的引數。比如我們想遍歷一個Map,我們想採用Groovy的方式,通過檢視文件,發現它有如下兩個方法,看起來和遍歷有關:

image
可以發現,這兩個each方法的引數都是一個閉包,那麼我們如何知道閉包的引數呢?當然不能靠猜,還是要查文件。

通過文件可以發現,這個閉包的引數還是不確定的,如果我們傳遞的閉包是一個引數,那麼它就把entry作為引數;如果我們傳遞的閉包是2個引數,那麼它就把key和value作為引數。
按照這種提示,我們來嘗試遍歷下:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def emptyMap = [:]
def test = ["id":1, "name":"renyugang", "isMale":true]
test.each { key, value ->
println "two parameters, find [${key} : ${value}]"
}
test.each {
println "one parameters, find [${it.key} : ${it.value}]"
}
outputs:
two parameters, find [id : 1]
two parameters, find [name : renyugang]
two parameters, find [isMale : true]
one parameters, find [id : 1]
one parameters, find [name : renyugang]
one parameters, find [isMale : true]
</pre>
另外一個eachWithIndex方法教給大家練習,自己查文件,然後嘗試用這個方法去遍歷。
試想一下,如果你不知道查文件,你又怎麼知道each方法如何使用呢?光靠從網上搜,API文件中那麼多介面,搜的過來嗎?記得住嗎?
4. 加強的IO
在Groovy中,檔案訪問要比Java簡單的多,不管是普通檔案還是xml檔案。怎麼使用呢?還是來查文件。

根據File的eachLine方法,我們可以寫出如下遍歷程式碼,可以看到,eachLine方法也是支援1個或2個引數的,這兩個引數分別是什麼意思,就需要我們學會讀文件了,一味地從網上搜例子,多累啊,而且很難徹底掌握:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def file = new File("a.txt")
println "read file using two parameters"
file.eachLine { line, lineNo ->
println "${lineNo} ${line}"
}
println "read file using one parameters"
file.eachLine { line ->
println "${line}"
}
outputs:
read file using two parameters
read file using one parameters
除了eachLine,File還提供了很多Java所沒有的方法,大家需要瀏覽下大概有哪些方法,然後需要用的時候再去查就行了,這就是學習Groovy的正道。
下面我們再來看看訪問xml檔案,也是比Java中簡單多了。 Groovy訪問xml有兩個類:XmlParser和XmlSlurper,二者幾乎一樣,在效能上有細微的差別,如果大家感興趣可以從文件上去了解細節,不過這對於本文不重要。
在下面的連結中找到XmlParser的API文件,參照例子即可程式設計,
http://docs.groovy-lang.org/docs/latest/html/api/ 。
假設我們有一個xml,attrs.xml,如下所示:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
<resources>
<declare-styleable name="CircleView">
<attr name="circle_color" format="color">#98ff02</attr> <attr name="circle_size" format="integer">100</attr> <attr name="circle_title" format="string">renyugang</attr>
</declare-styleable>
</resources>
</pre>
那麼如何遍歷它呢?
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def xml = new XmlParser().parse(new File("attrs.xml"))
// 訪問declare-styleable節點的name屬性
println xml['declare-styleable'].@name[0]
// 訪問declare-styleable的第三個子節點的內容
println xml['declare-styleable'].attr[2].text()
outputs:
CircleView
renyugang
</pre>
更多的細節都可以從我發的那個連結中查到,大家有需要查文件即可。
Groovy的其他特性
除了本文中已經分析的特性外,Groovy還有其他特性。
- Class是一等公民
在Groovy中,所有的Class型別,都可以省略.class,比如:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
func(File.class)
func(File)
def func(Class clazz) {
}
</pre>
- Getter和Setter
在Groovy中,Getter/Setter和屬性是預設關聯的,比如:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
class Book {
private String name String getName() { return name } void setName(String name) { this.name = name }
}
class Book {
String name
}
</pre>
上述兩個類完全一致,只有有屬性就有Getter/Setter;同理,只要有Getter/Setter,那麼它就有隱含屬性。
- with操作符
在Groovy中,當對同一個物件進行操作時,可以使用with,比如:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
Book bk = new Book()
bk.id = 1
bk.name = "android art"
bk.press = "china press"
可以簡寫為:
Book bk = new Book()
bk.with {
id = 1 name = "android art" press = "china press"
}
</pre>
- 判斷是否為真
在Groovy中,判斷是否為真可以更簡潔:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
if (name != null && name.length > 0) {}
可以替換為:
if (name) {}
</pre>
- 簡潔的三元表示式
在Groovy中,三元表示式可以更加簡潔,比如:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def result = name != null ? name : "Unknown"
// 省略了name
def result = name ?: "Unknown"
</pre>
- 簡潔的非空判斷
在Groovy中,非空判斷可以用?表示式,比如:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
if (order != null) {
if (order.getCustomer() != null) { if (order.getCustomer().getAddress() != null) { System.out.println(order.getCustomer().getAddress()); } }
}
可以簡寫為:
println order?.customer?.address
</pre>
- 使用斷言
在Groovy中,可以使用assert來設定斷言,當斷言的條件為false時,程式將會丟擲異常:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def check(String name) {
// name non-null and non-empty according to Groovy Truth assert name // safe navigation + Groovy Truth to check assert name?.size() > 3
}
</pre>
- switch方法
在Groovy中,switch方法變得更加靈活,可以同時支援更多的引數型別:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
def x = 1.23
def result = ""
switch (x) {
case "foo": result = "found foo" // lets fall through case "bar": result += "bar" case [4, 5, 6, 'inList']: result = "list" break case 12..30: result = "range" break case Integer: result = "integer" break case Number: result = "number" break case { it > 3 }: result = "number > 3" break default: result = "default"
}
assert result == "number"
</pre>
- ==和equals
在Groovy中,==相當於Java的equals,,如果需要比較對個物件是否是同一個,需要使用.is()。
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
Object a = new Object()
Object b = a.clone()
assert a == b
assert !a.is(b)
編譯、執行Groovy
可以安裝Groovy sdk來編譯和執行。但是我並不想搞那麼麻煩,畢竟我們的最終目的只是學習Gradle。
推薦大家通過這種方式來編譯和執行Groovy。
在當面目錄下建立build.gradle檔案,在裡面建立一個task,然後在task中編寫Groovy程式碼即可,如下所示:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
task(yugangshuo).doLast {
println "start execute yuangshuo" haveFun()
}
def haveFun() {
println "have fun!" System.out.println("have fun!"); 1 def file1 = new File("a.txt") def file2 = new File("a.txt") assert file1 == file2 assert !file1.is(file2)
}
class Book {
private String name String getName() { return name } void setName(String name) { this.name = name }
}
</pre>
只需要在haveFun方法中編寫Groovy程式碼即可,如下命令即可執行:
<pre style="margin: 1em 0px; padding: 0px 1em; max-width: 100%; box-sizing: inherit; word-wrap: break-word !important; color: rgb(51, 51, 51); font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: 0.544000029563904px; orphans: auto; text-align: justify; text-indent: 0px; text-transform: none; widows: 1; word-spacing: 0px; -webkit-text-stroke-width: 0px; overflow: auto; font-size: 14px; border-radius: 4px; background-color: rgb(235, 238, 245);">
gradle yugangshuo
</pre>