當你在groovy中定義類的時候須要指定包名,這和java中相似很少介紹。html
groovy中的導入也跟java相似,有一下五種:java
groovy默認導入了一下幾個包和類:git
import java.lang.* import java.util.* import java.io.* import java.net.* import groovy.lang.* import groovy.util.* import java.math.BigInteger import java.math.BigDecimal
普通導入即全類名導入github
// importing the class MarkupBuilder import groovy.xml.MarkupBuilder // using the imported class to create an object def xml = new MarkupBuilder() assert xml != null
這個也不用多說工具
import groovy.xml.* def markupBuilder = new MarkupBuilder() assert markupBuilder != null assert new StreamingMarkupBuilder() != null
import static java.lang.String.format class SomeClass { String format(Integer i) { i.toString() } static void main(String[] args) { assert format('String') == 'String' assert new SomeClass().format(Integer.valueOf(1)) == '1' } }
靜態簡稱導入在java中是沒有的,這裏解釋一下。Calendar
有一個靜態方法getInstance()
能夠得到Calendar
的實例,既然是靜態方法咱們就可使用上面的靜態導入來直接調用getInstance()
方法,但getInstance()
這個方法在被調用的時候有誤導性,不清楚的還覺得是用於得到當前類的實例,因此這時候靜態簡稱導入
就發揮做用了:佈局
import static Calendar.getInstance as now assert now().class == Calendar.getInstance().class
這樣咱們就直接能夠調用now()
來得到Calendar
的實例了,這樣是否是清晰了不少?學習
讀了Groovy基本句法應該瞭解groovy是能夠同時支持編寫腳本和類的,接下來就來學習一下他們之間的關係。ui
先看下面的例子this
class Main { static void main(String... args) { println 'Groovy world!' } }
這是java的傳統寫法,這裏把須要執行的代碼寫在了main中,在groovy中達到一樣的效果就簡單多了:.net
println 'Groovy world!'
雖然上面的是一行腳本語言,但在運行的時候Groovy
仍是將其轉換成類來處理,相似以下的類:
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) } }
能夠看出來須要執行的代碼被放入了run()
方法中。
這裏咱們能夠簡單證明一下上面的說法:
首先新建一個main.groovy
的腳本文件,內容以下:
println 'hello world !'
接着時候groovyc
命令將main.groovy
轉換成字節碼main.class
,接着使用class文件的閱讀工具查看其內容以下:
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // import groovy.lang.Binding; import groovy.lang.Script; import org.codehaus.groovy.runtime.InvokerHelper; import org.codehaus.groovy.runtime.callsite.CallSite; public class main extends Script { public main() { CallSite[] var1 = $getCallSiteArray(); } public main(Binding context) { CallSite[] var2 = $getCallSiteArray(); super(context); } public static void main(String... args) { CallSite[] var1 = $getCallSiteArray(); var1[0].call(InvokerHelper.class, main.class, args); } public Object run() { CallSite[] var1 = $getCallSiteArray(); return var1[1].callCurrent(this, "hello world !"); } }
雖然生成的和上面略有不一樣,但的確是被轉換爲一個繼承Script
的類,並且須要運行的代碼被放在run方法中了。
接下來咱們看看腳本中定義的方法會被怎麼轉換。
method.groovy
println 'Hello' int power(int n) { 2**n } println "2^6==${power(6)}"
仍是按照以前的轉換方法,獲得結果:
public class method extends Script { public method() { CallSite[] var1 = $getCallSiteArray(); } public method(Binding context) { CallSite[] var2 = $getCallSiteArray(); super(context); } public static void main(String... args) { CallSite[] var1 = $getCallSiteArray(); var1[0].call(InvokerHelper.class, method.class, args); } public Object run() { CallSite[] var1 = $getCallSiteArray(); var1[1].callCurrent(this, "Hello"); return !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()?var1[4].callCurrent(this, new GStringImpl(new Object[]{Integer.valueOf(this.power(6))}, new String[]{"2^6==", ""})):var1[2].callCurrent(this, new GStringImpl(new Object[]{var1[3].callCurrent(this, Integer.valueOf(6))}, new String[]{"2^6==", ""})); } public int power(int n) { CallSite[] var2 = $getCallSiteArray(); return DefaultTypeTransformation.intUnbox(var2[5].call(Integer.valueOf(2), Integer.valueOf(n))); } }
能夠看到power()
被定義在了method這個類中。
下來再來看看變量是怎麼被轉換的
variables1.groovy
int x = 1 int y = 2 assert x+y == 3
轉換結構以下:
public class variables1 extends Script { public variables1() { CallSite[] var1 = $getCallSiteArray(); } public variables1(Binding context) { CallSite[] var2 = $getCallSiteArray(); super(context); } public static void main(String... args) { CallSite[] var1 = $getCallSiteArray(); var1[0].call(InvokerHelper.class, variables1.class, args); } public Object run() { CallSite[] var1 = $getCallSiteArray(); byte x = 2; byte y = 3; return BytecodeInterface8.isOrigInt() && !__$stMC && !BytecodeInterface8.disabledStandardMetaClass()?var1[3].callCurrent(this, Integer.valueOf(x + y)):var1[1].callCurrent(this, var1[2].call(Integer.valueOf(x), Integer.valueOf(y))); } }
能夠看出來x,y被定義爲了run方法的佈局變量。
接着看:
variables2.groovy
x = 2 y = 3 println x+y
轉換結果以下
public class variables2 extends Script { public variables2() { CallSite[] var1 = $getCallSiteArray(); } public variables2(Binding context) { CallSite[] var2 = $getCallSiteArray(); super(context); } public static void main(String... args) { CallSite[] var1 = $getCallSiteArray(); var1[0].call(InvokerHelper.class, variables2.class, args); } public Object run() { CallSite[] var1 = $getCallSiteArray(); byte var2 = 2; ScriptBytecodeAdapter.setGroovyObjectProperty(Integer.valueOf(var2), variables2.class, this, (String)"x"); byte var3 = 3; ScriptBytecodeAdapter.setGroovyObjectProperty(Integer.valueOf(var3), variables2.class, this, (String)"y"); return var1[1].callCurrent(this, var1[2].call(var1[3].callGroovyObjectGetProperty(this), var1[4].callGroovyObjectGetProperty(this))); } }
額,看不太懂了,但能夠確定x,y沒有被定義成run的成員變量。
綜合上面的兩個變量轉換的例子,請判斷下面這個腳本能夠正確執行嗎?
int x = 1; def getDoubleX(){ x*2 ; } println getDoubleX()
答案是不能,這裏的x會被定義成run的成員變量,而getDouble這個方法是訪問不到x的,這裏須要注意。
以上就是關於Groovy中腳本和類的關係了,更多詳細內容請參考: