腳本與類
Groovy代碼文件與class文件的對(duì)應(yīng)關(guān)系
作為基于JVM的語(yǔ)言,Groovy可以非常容易的和Java進(jìn)行互操作,但也需要編譯成class文件后才能運(yùn)行,所以了解Groovy代碼文件和class文件的對(duì)應(yīng)關(guān)系,有助于更好地理解Groovy的運(yùn)行方式和結(jié)構(gòu)。
對(duì)于沒(méi)有任何類定義
如果Groovy腳本文件里只有執(zhí)行代碼称龙,沒(méi)有定義任何類(class),則編譯器會(huì)生成一個(gè)Script的子類戳晌,類名和腳本文件的文件名一樣鲫尊,而腳本的代碼會(huì)被包含在一個(gè)名為run的方法中,同時(shí)還會(huì)生成一個(gè)main方法沦偎,作為整個(gè)腳本的入口疫向。
對(duì)于僅有一個(gè)類
如果Groovy腳本文件里僅含有一個(gè)類,而這個(gè)類的名字又和腳本文件的名字一致豪嚎,這種情況下就和Java是一樣的搔驼,即生成與所定義的類一致的class文件, Groovy類都會(huì)實(shí)現(xiàn)groovy.lang.GroovyObject接口。
對(duì)于多個(gè)類
如果Groovy腳本文件含有一個(gè)或多個(gè)類侈询,groovy編譯器會(huì)很樂(lè)意地為每個(gè)類生成一個(gè)對(duì)應(yīng)的class文件舌涨。如果想直接執(zhí)行這個(gè)腳本,則腳本里的第一個(gè)類必須有一個(gè)static的main方法扔字。
對(duì)于有定義類的腳本
如果Groovy腳本文件有執(zhí)行代碼, 并且有定義類, 那么所定義的類會(huì)生成對(duì)應(yīng)的class文件, 同時(shí), 腳本本身也會(huì)被編譯成一個(gè)Script的子類囊嘉,類名和腳本文件的文件名一樣
1. public static void main vs script
Groovy 同時(shí)支持腳本和類温技。以以下代碼為例:
Main.groovy
class Main {
static void main(String... args) {
println 'Groovy world!'
}
}
定義類,名稱是Main
main方法用作類的主要方法 public static void main(String[])
方法的主體println 'Groovy world!'
這是典型的java代碼扭粱,其中代碼必須嵌入到一個(gè)類中方可執(zhí)行舵鳞。Groovy 使它更簡(jiǎn)潔:
Main.groovy
println 'Groovy world!'
腳本可以被視為類,無(wú)需聲明它琢蛤,但存在一些差異蜓堕。
2. 腳本轉(zhuǎn)換為類
腳本始終會(huì)被編譯為類。Groovy 編譯器將為你編譯該類虐块,并將腳本的正文復(fù)制到方法中俩滥。因此,前面的示例的編譯情況類似如下:
Main.groovy
import org.codehaus.groovy.runtime.InvokerHelper
class Main extends Script {
def run() {
println 'Groovy world!'
}
static void main(String[] args) {
InvokerHelper.runScript(Main, args)
}
}
類繼承自 groovy.lang.Script
groovy.lang.Script
需要一個(gè)帶返回值的方法run
腳本正文進(jìn)入方法run
該方法是自動(dòng)生成的main
并委托對(duì)方法執(zhí)行腳本run
如果腳本位于文件中贺奠,則該文件的基名用于確定生成的腳本類的名稱
3.方法
可以定義方法到腳本中,如下所示
int fib(int n) {
n < 2 ? 1 : fib(n-1) + fib(n-2)
}
assert fib(10)==89s
您還可以混合方法和代碼错忱。生成的腳本類將所有方法都引入腳本類儡率,并將所有腳本體組合到方法中:
//腳本開(kāi)始
println 'Hello'
//在腳本正文中定義方法
int power(int n) { 2**n }
//腳本繼續(xù)
println "2^6==${power(6)}"
此代碼在內(nèi)部轉(zhuǎn)換為:
import org.codehaus.groovy.runtime.InvokerHelper
class Main extends Script {
int power(int n) { 2** n}
def run() {
println 'Hello'
println "2^6==${power(6)}"
}
static void main(String[] args) {
InvokerHelper.runScript(Main, args)
}
}
4.變量
腳本中的變量不需要類型定義。這意味著此腳本:
int x = 1
int y = 2
assert x+y == 3
行為與以下行為相同:
x = 1
y = 2
assert x+y == 3
但是以清,兩者之間存在語(yǔ)義差異:
如果變量聲明為第一個(gè)示例中儿普,則它是局部變量。它將在編譯器生成的方法run
中聲明掷倔,并且在腳本主體之外不可見(jiàn)眉孩。特別是此變量在腳本的其他方法中不可見(jiàn)。
如果變量未聲明類型或def占位符勒葱,則進(jìn)入腳本綁定浪汪。綁定從方法中可見(jiàn),如果使用腳本與應(yīng)用程序交互凛虽,并且需要在腳本和應(yīng)用程序之間共享數(shù)據(jù)死遭,則綁定尤其重要。
如果希望變量成為類的字段而不進(jìn)入Binding
凯旋,可以使用@Field注釋呀潭。