Groovy++使用注意的時候

最近使用Groovy處理一些數據工作,發現其速度慢的不行,也懶得對代碼進行優化,打算使用Groovy++加速一下,發現一些代碼有問題:

long a = 0

1000.times { int b->

a+=b

}

都過不了~

 

1.Groovy++編譯時檢查更嚴格

例1:

/* Leave it commented to run the dynamic Groovy version; Uncomment to run Groovy++ version */ //@Typed package test def x = { List list -> list.size() } x(1)

對Groovy,上述代碼編譯不會出錯,但運行時會出錯。因爲我們調用的是x(Integer),而定義的是x(List)。

對Groovy++,編譯時即報錯:"Cannot find method { List -> ...}.doCall(int)"。

例2:

/* Commented -> dynamic Groovy version; Uncommented -> Groovy++ version */ //@Typed package test class Foo { def greet() {println "Foo says hello"} } class Bar { def greet() {println "Bar says hello"} } def c = {greeter -> greeter.greet()} c(new Foo()) c(new Bar())

對Groovy,得益於duck-typing,上述代碼編譯時和運行時都不會出錯。

對Groovy++,則會出錯:"Cannot find method Object.greet()" ,因爲它會依照閉包參數的靜態類型來做判斷。

2.通過ExpandoMetaClass即時修改類型。

例3:

/* Commented -> dynamic Groovy version; Uncommented -> Groovy++ version */ //@Typed package test String.metaClass.foo = { -> println "foo called" } "".foo() /* call my new method */

對Groovy,上述代碼運行得很好,並動態給String增加foo方法。

對Groovy++,靜態模式下不支持這一特性,“Mixed”模式可以解決這一問題,既享用動態特性,又保持靜態檢查。如下例所示

例4:

@Typed(TypePolicy.MIXED) package test String.metaClass.foo = { -> println "foo called" } // supported "".foo()

3.Groovy++閉包更像是Java的內嵌類

在Java中,內嵌類不能引用其外部範圍的非final成員。如下述代碼編譯將出錯。

例5:

void foo(){ String data = ""; class Inner { void innerFoo() { System.out.println(data); } } }

groovy把閉包看作是內嵌類,但是不限制對外部非final成員的訪問,因此下屬代碼可以在Groovy中運行

例6:

void foo(){ String data = 'original'; def cl = {data = 'changed'} // access non-final data of its outer scope cl() assert data == 'changed' } foo()

Groovy++與Java更加接近,只允許以只讀方式訪問非final數據成員。如下例,如果試圖修改這些成員,則會報 錯:"Cannot modify final field test.Test$foo$1.data"

例7:

@Typed package test void foo(){ String data = 'original'; def cl = {data = 'changed'} } foo()

之所以這樣,項目領導Alex Tkachman解釋主要是避免並行運行風險。但如果不做並行運算,是否有什麼解決之道?參見下例,用groovy.lang.Reference:

例8:

@Typed package test void foo(){ Reference data = ['original'] def cl = {data = 'changed'} // now even Groovy++ supports modification of non-final outer scope data cl() assert data == 'changed' } foo()

4.Groovy++不再直接訪問私有成員

Groovy沒有限制從外部訪問一個類的私有成員,下例將正常運行。

例9:

/* Commented -> dynamic Groovy version; Uncommented -> Groovy++ version */ //@Typed package test class SecretService { String secret = "secret" String getSecret() { "covered-" + secret } private launchOperation() { "launched" } } def ss = new SecretService() assert ss.@secret == "secret" // can access the private field directly assert ss.launchOperation() == "launched" // can access the private method

Groovy++ 則在編譯時限制這種訪問,對Groovy++,上面例子"ss.@secret" 會導致 "Cannot access field test.SecretService.secret"; "ss.launchOperation()" 會導致 "Cannot access method SecretService.launchOperation()"。

5.還有一些小的差別

例10:Script binding 變量

/* Commented -> dynamic Groovy version; Uncommented -> Groovy++ version */ //@Typed package test foo = "foo" assert foo == "foo"

上述例子對Groovy沒有問題,變量foo是在script中綁定的。但在Groovy++ 中不支持,如果要在Groovy中使用這一特性,得用@Typed(TypePolicy.MIXED)標註方式。

例11:對map的屬性風格訪問

/* Commented -> dynamic Groovy version; Uncommented -> Groovy++ version */ //@Typed package test def map = [key1: "value1"] assert map.key1 == "value1"

map.key1這種方式訪問map,對Groovy沒問題,但 Groovy++不支持,除非用MIXED模式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章