groovy與java語法區別
groovy與java語法區別
Groovy試圖對Java開發人員盡可能地兼容。在設計Groovy時,遵循最不意外的原則,尤其是對於那些來自Java背景的開發人員。
這裏我們列出了Java和Groovy之間的所有主要區別。
1.額外的關鍵字
Groovy中比Java多一些關鍵字,不要將它們用於變量名稱等。
as
def
in
trait
2.數組初始化
在Groovy中,{...}塊保留用於閉包。這意味著您無法使用以下語法創建數組字面量:
// java初始化
int[] array = { 1, 2, 3}
// groovy初始化必須使用方括號
int[] array = [1,2,3]
3.基本類型和包裝類
因為Groovy將Objects用於所有內容,所以它會自動對基本類型進行包裝。因此,它不遵循Java的提升行為優先於自動裝箱。這是一個使用int的例子
int i // groovy 自動裝箱
m(i)
// Java 會調用這個 基本類型提升優先於自動裝箱
void m(long l) {
println "in m(long)"
}
// groovy會調用這個 自動裝箱了已經
void m(Integer i) {
println "in m(Integer)"
}
4.==的行為
在Java中==表示基本類型或對象的標識的相等性。
在Groovy中== 如果它們是Comparable,轉換為a.compareTo(b)== 0,否則轉換為a.equals(b)
要檢查一致,有is方法。例如a.is(b)中。
5.方法重載
在Groovy中,將在運行時選擇要調用的方法,這稱為運行時調度或多態。這意味著將根據運行時參數的類型選擇方法。在Java中,這是相反的:重載在編譯時根據聲明的類型選擇方法。
以下代碼編寫為Java代碼,可以在Java和Groovy中編譯,但它的行為會有所不同:
int method(String arg) { return 1; } int method(Object arg) { return 2; } Object o = "Object"; int result = method(o); //在Java中,=2 assertEquals(2, result); //在Groovy中:=1 assertEquals(1, result);
這是因為Java將使用靜態信息類型,即o被聲明為Object,而Groovy將在運行時選擇實際調用方法。由於它實際是String的,因此調用String版本。
6. GStrings
由於雙引號字符串文字被解釋為GString值,如果使用Groovy和Java編譯器編譯一個包含美元字符的字符串字面量的類,Groovy可能會因編譯錯誤失敗或產生微妙的不同代碼。
雖然通常情況下,如果API聲明了參數的類型,Groovy將在GString和String之間自動轉換,請註意接受Object參數的Java API,然後檢查實際類型。
7. String and Character 字面量
Groovy中單引號文字用於String,而雙引號結果用於String或GString,具體取決於字面量中是否有插值。
assert ‘c‘.getClass()==String
assert "c".getClass()==String
assert "c${1}".getClass() in GString // 字面量中有插值 $
只有在分配給char類型的變量時,Groovy才會自動將單字符String轉換為char。當使用char類型的參數調用方法時,我們需要顯式轉換或確保已提前轉換。
// 提前轉化
char a=‘a‘
assert Character.digit(a, 16)==10 : ‘But Groovy does boxing‘
// 顯式轉化
assert Character.digit((char) ‘a‘, 16)==10
try {
assert Character.digit(‘a‘, 16)==10
assert false: ‘Need explicit cast‘
} catch(MissingMethodException e) {
}
Groovy支持兩種類型的轉換,在轉換為char時,在轉換多字符的串時存在細微差別。 Groovy樣式轉換更寬松,將采用第一個字符,而C樣式轉換將失敗,但異常。
// 單字符的串 轉換一致
assert ((char) "c").class==Character
assert ("c" as char).class==Character
// 多字符的串 轉換規則不一樣
try {
((char) ‘cx‘) == ‘c‘
assert false: ‘will fail - not castable‘
} catch(GroovyCastException e) {
}
assert (‘cx‘ as char) == ‘c‘
// 采用第一個字符
assert ‘cx‘.asType(char) == ‘c‘
8.默認導入
默認情況下導入所有這些包和類,即您不必使用顯式import語句來使用它們:
java.io.*
java.lang.*
java.math.BigDecimal
java.math.BigInteger
java.net.*
java.util.*
groovy.lang.*
groovy.util.*
9.包範圍可見性
在Groovy中,省略字段上的修飾符不會導致像Java一樣的包私有字段:
class Person {
String name
}
相反,它用於創建屬性,即私有字段,關聯的getter和關聯的setter。 可以通過使用@PackageScope註釋來創建包私有字段:
class Person {
@PackageScope String name
}
10.ARM塊
Groovy不支持Java 7中的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
}
}
11.內部類
匿名內部類和嵌套類的實現是Java引領的,但是您不應該排除Java語言規範糾結為什麽不同。這些實現看起來很像我們為groovy.lang.Closure做的,有一些好處和一些差異。例如,訪問私有字段和方法可能會成為一個問題,但另一方面,局部變量不一定是final的。
11.1 靜態內部類
class A {
// 靜態內部類B
static class B {}
}
new A.B()
靜態內部類的使用是最受支持的。如果你絕對需要一個內部類,你應該把它變成一個靜態類。
11.2 匿名內部類
import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
CountDownLatch called = new CountDownLatch(1)
Timer timer = new Timer()
// 匿名內部類 實現了TimerTask接口
timer.schedule(new TimerTask() {
void run() {
called.countDown()
}
}, 0)
assert called.await(10, TimeUnit.SECONDS)
11.3 創建非靜態內部類的實例
public class Y {
// 非靜態內部類X
public class X {}
public X foo() {
return new X();
}
public static X createX(Y y) {
// 創建非靜態內部類實例
return y.new X();
}
}
Groovy不支持y.new X()語法。相反,您必須編寫新的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。基本上相同的規則適用於調用構造函數。
例如,您可能會編寫新的X()而不是新的X(this)。由於這也可能是常規方式,我們尚未找到防止此問題的好方法。
12.Lambdas
Java 8支持lambda和方法引用:
Runnable run = () -> System.out.println("Run");
list.forEach(System.out::println);
Java 8 lambdas可以或多或少地被視為匿名內部類。 Groovy不支持該語法,但有閉包:
// Groovy
Runnable run = { println ‘run‘ }
list.each { println it } // or list.each(this.&println)
12.轉換
Java會自動擴展和縮小轉換
基礎類型 如byte、int、。。
groovy與java語法區別