1.groovy所有的包和classes是默認被導入
2.在groovy中,方法的調用是在運行時被選擇。這被稱為運行時調度和多方法。根據運行時參數類型選擇方法。
在java中,這個是相反的,在編譯時,根據定義的類型, 選擇方法。
以下代碼以Java代碼的形式編寫,可以在Java和Groovy中編譯,但其行為會有所不同:
1 int method(String arg) { 2 return 1; 3 } 4 int method(Object arg) { 5 return 2; 6 } 7 Object o = "Object"; 8 int result = method(o);
在java中 result的值是2,
在groovy中的值是1
java使用的是靜態信息類型,o被聲明為Object;然而groovy是在運行時選擇,這個方法真正被調用的時候。因為o是一個String所以調運String的版本。
3.數組的初始化: 在Groovy中,{…}塊保留給閉包。
java:
int[] array = { 1, 2, 3 }
groovy
int[] array = [ 1, 2, 3]
4.包范圍的可見性
在groovy中,省略字段的修飾符,不會導致像在java中變成一個包私有字段。
相反,在groovy創建一個屬性,即私有字段,關聯getter,關聯setter
通過注解@PackageScope來創建一個包私有字段
1 class Perso{ 2 @PackageScope String name 3 }
5.ARM(Automatic Resource Management)模塊( 自動資源管理)
Groovy不支持Java7中的ARM模塊。
相反, Groovy提供了依賴於閉包的各種方法,閉包具有相同的效果,同時更具有慣用性
Path file = Paths.get("/path/to/file"); Charset charset = Charset.forName("UTF-8"); try (BufferedReader reader = Files.newBufferedReader(file, charset)) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); }
能被寫成
new File('/path/to/file').eachLine('UTF-8') { println it }
如果你想要一個更接近Java的版本
new File('/path/to/file').withReader('UTF-8') { reader -> reader.eachLine { println it } }
6.內部類
匿名內部類和嵌套類的實現遵循Java的指導原則,但是您不應該去掉Java語言規范,而繼續對不同的事情搖頭嘆息。實現看起來很像我們對groov.lang.Closure所做的。有一些好處也有一些不同。例如,訪問私有字段和方法可能成為一個問題,但另一方面,局部變量不一定是最終的。
靜態內部類:
class A { static class B {} } new A.B()
靜態內部類的使用最受支持。如果你絕對需要一個內部類,你應該設置它是一個靜態內部類。
匿名內部類:
import java.util.concurrent.CountDownLatch import java.util.concurrent.TimeUnit CountDownLatch called = new CountDownLatch(1) Timer timer = new Timer() timer.schedule(new TimerTask() { void run() { called.countDown() } }, 0)
assert called.await(10, TimeUnit.SECONDS)
創建一個非靜態的內部類的實例
在Java中:
public class Y { public class X {} public X foo() { return new X(); } public static X createX(Y y) { return y.new X(); }}
Groovy中不支持 y.new X() 。代替,你必須寫成 new X(y), 就像下面的代碼
public class Y { public class X {} public X foo() { return new X() } public static X createX(Y y) { return new X(y) } }
Groovy支持使用一個參數調用方法,而不提供參數參數,那么參數的值將為null。相同的規則應用在調用構造函數上。有一個危險,你寫 new X() 代替 new X(this)。 因為這可能也是常規的方法,我們還沒有找到一個好的方法來預防這個問題。
7.Lambdas
Java8支持lambdas和方法引用
Runnable run = () -> System.out.println("Run");
list.forEach(System.out::println);
Java8 lambdas 或多或少能看做事匿名內部類。
Groovy不支持這種語法,但是有閉包代替:
Runnable run = { println 'run' } list.each { println it } // or list.each(this.&println)
8.GString
雙引號的字符串的字面值被解釋為GString類型的值。如果用Groovy和Java編譯一個包含$符號的String,Groovy可能會編譯報錯或者產生微妙的不同代碼
如果API 聲明的參數的類,Groovy自動轉換在GString和String之間。當心Java APIs,接受一個對象的參數並且檢查實際類型。
9.String Character
在Groovy,單引號字面值被使用為String,雙引號的結果是 String 或者 GString,取決於在字面值中是否有插入。
Groovy自動轉換單個字符的字符串成為字符類型,僅僅是當分配的變量類型char。
當調用參數類型是char的方法時,我們需要顯示的轉換 或者確保這個值被提前轉換。
Groovy支持2種風格的轉換,當轉換的是多個字符的字符串時,有一些不同。Groovy風格是更加寬容的,將轉換第一個字符,然而C風格的轉換將以exception失敗
10.原始類型和包裝類型
因為Groovy什么都是對象,它自動引用到原始類型。正因為這樣,它不遵循java的行為,擴大 優先級到裝箱
int i m(i) void m(long l) { // 1 println "in m(long)" } void m(Integer i) { //2 println "in m(Integer)" }
1.java調用這個方法,認為 擴展 優先於 拆箱
2.Groovy調用這個方法,因為所有的原始類型引用到他們的的包裝類。
11.==
在Java中 == 意味着 原始類型相同或 對象的一致性。
在Groovy 中 如果他們是可比較的並且a.equals(b), == 轉換成a.compareTo(b)==0。為了核查一致性,可以使用is,例如 a.is(b)
12.轉換(conversions)
13.額外的字段
Groovy中的關鍵詞比Java中的多一些。不要將它們用於變量名等
as、def、in、trait