一個(gè)java程序員剛開始使用Groovy的時(shí)候盲憎,不可避免的滿腦子想的都是java,當(dāng)熟悉Groovy后就會(huì)代碼會(huì)逐漸符合Groovy語言習(xí)慣,從而變得更加高產(chǎn)凄敢。下面介紹一下一些通用的Groovy語法:
1、不需要分號
學(xué)過C/C++/C#/java的同學(xué)都會(huì)對分號很熟悉湿痢,我們使用的如此頻繁涝缝,幾乎放在每一行的末尾。Groovy支持99%的java語法譬重,甚至可以在Groovy代碼中直接粘貼java代碼拒逮,然而在Groovy中分號是可選的,你可以省略他們臀规。
2滩援、return關(guān)鍵字可省略
在Groovy中,方法的最后一句表達(dá)式可作為返回值返回塔嬉,而不需要return關(guān)鍵字玩徊。
String toString() { return "a server" }
String toString() { "a server" }
但有時(shí)候省略return
關(guān)鍵字并不是一個(gè)好主意
def props() {
def m1 = [a: 1, b: 2]
m2 = m1.findAll { k, v -> v % 2 == 0 }
m2.c = 3
m2
}
在這種情況下,明確的使用return
關(guān)鍵字會(huì)更具可讀性谨究。
3恩袱、def 和 類型
在Groovy中使用def
關(guān)鍵字定義的變量類型都是Object,定義方法是记盒,通吃鞲颍可以省略def
關(guān)鍵字,盡量別def
和類型混用纪吮,避免這種寫法def String name = "Guillaume"
俩檬。
定義方法時(shí),如果參數(shù)沒有類型碾盟,我們可以省略def
:
void doSomething(param1, param2) { }
定義類的構(gòu)造器時(shí)棚辽,避免添加def
關(guān)鍵字:
class MyClass {
MyClass() {}
}
4、默認(rèn)是public權(quán)限
默認(rèn)情況下冰肴,Groovy的classes和方法是public
權(quán)限屈藐,所以我們可以省略public
關(guān)鍵字榔组,除非我們想使用private
:
class Server {
String toString() { "a server" }
}
5、省略圓括號()
Groovy允許你在頂級表達(dá)式中省略圓括號联逻,例如println
:
println "Hello"
method a, b
某些情況下搓扯,Groovy不允許省略圓括號,比如:
def foo(n) { n }
println foo 1 // won't work
6包归、Classes是一等公民
在Groovy中.class
后綴不是必須的锨推,類似于java的instance
。例如:
connection.doPost(BASE_URI + "/modify.hqu", params, ResourcesResponse.class)
使用GStrings公壤,并使用class一等公民:
connection.doPost("${BASE_URI}/modify.hqu", params, ResourcesResponse)
7换可、Getters and Setters
getter和setter方法來自屬性,Groovy中厦幅,提供了一個(gè)簡短的獲取和設(shè)置屬性的方法沾鳄,你可以省略getter和setter:
resourceGroup.getResourcePrototype().getName() == SERVER_TYPE_NAME
resourceGroup.resourcePrototype.name == SERVER_TYPE_NAME
resourcePrototype.setName("something")
resourcePrototype.name = "something"
當(dāng)你在Groovy中創(chuàng)建一個(gè)beans的時(shí)候,通常我們稱為POGOS(Plain Old Groovy Objects)确憨,Groovy會(huì)自動(dòng)幫我們創(chuàng)建getter/setter方法译荞,所以你可以把
class Person {
private String name
String getName() { return name }
void setName(String name) { this.name = name }
}
替換為
class Person {
String name
}
當(dāng)你對getter/setter方法有特殊要求,你盡可提供自己的方法缚态,Groovy默認(rèn)的getter/setter方法會(huì)被替換磁椒。
8、使用命名的參數(shù)初始化beans和默認(rèn)的構(gòu)造器
有一個(gè)bean
class Server {
String name
Cluster cluster
}
初始化一個(gè)實(shí)例的時(shí)候你可能會(huì)這樣寫:
def server = new Server()
server.name = "Obelix"
server.cluster = aCluster
其實(shí)你可以用帶命名的參數(shù)的默認(rèn)構(gòu)造器玫芦,會(huì)大大減少代碼量:
def server = new Server(name: "Obelix", cluster: aCluster)
9、在同一個(gè)bean中使用with()來重復(fù)某一個(gè)操作
當(dāng)更新一個(gè)實(shí)例的時(shí)候本辐,你可以使用with()來省略相同的前綴桥帆,java中你必須這樣寫:
server.name = application.name
server.status = status
server.sessionCount = 3
server.start()
server.stop()
Groovy中則可以使用with():
server.with {
name = application.name
status = status
sessionCount = 3
start()
stop()
}
10、Equals 和 ==
Java里的==
等同于Groovy里的is()
方法慎皱,Groovy中的==
是更智能的equals()
老虫,比較兩個(gè)類的時(shí)候,你應(yīng)該使用a.is(b)
,而不是==
茫多。
Groovy中的==
可以自動(dòng)避免NullPointerException
異常:
替換
status != null && status.equals(ControlConstants.STATUS_COMPLETED)
為
status == ControlConstants.STATUS_COMPLETED
11祈匙、GStrings字符串分行
Java中,字符串過長需要換行時(shí)我們一般會(huì)這樣寫:
throw new PluginException("Failed to execute command list-applications:" +
" The group with name " +
parameterMap.groupname[0] +
" is not compatible group of type " +
SERVER_TYPE_NAME)
Groovy中你可以用 \ 字符:
throw new PluginException("Failed to execute command list-applications: \
The group with name ${parameterMap.groupname[0]} \
is not compatible group of type ${SERVER_TYPE_NAME}")
或者使用多行字符串"""
:
throw new PluginException("""Failed to execute command list-applications:
The group with name ${parameterMap.groupname[0]}
is not compatible group of type ${SERVER_TYPE_NAME)}""")
Groovy中天揖,單引號引起來的字符串是java字符串夺欲,不能使用占位符來替換變量,雙引號引起的字符串則是java字符串或者Groovy字符串今膊。
12些阅、一些操作數(shù)據(jù)結(jié)構(gòu)的方法
def list = [1, 4, 6, 9]
// Map的key默認(rèn)是字符串類型,可以省略雙引號
//你可以用()將keys包起來插入一個(gè)變量或者類作為key斑唬,例如 [(variableStateAcronym): stateName]
def map = [CA: 'California', MI: 'Michigan']
def range = 10..20
def pattern = ~/fo*/
// <<相當(dāng)于 add()
list << 5
// 調(diào)用包含方法
assert 4 in list
assert 5 in list
assert 15 in range
// subscript notation
assert list[1] == 4
// map添加key-value對
map << [WA: 'Washington']
// subscript notation
assert map['CA'] == 'California'
// property notation
assert map.WA == 'Washington'
// 匹配正則表達(dá)式
assert 'foo' =~ pattern
13市埋、switch方法
Groovy的switch方法更具實(shí)用性黎泣,可以接受更多的類型:
def x = 1.23
def result = ""
switch (x) {
case "foo": result = "found foo"
// lets fall through
case "bar": result += "bar"
case [4, 5, 6, 'inList']: result = "list"
break
case 12..30: result = "range"
break
case Integer: result = "integer"
break
case Number: result = "number"
break
case { it > 3 }: result = "number > 3"
break
default: result = "default"
}
assert result == "number"
types也可以調(diào)用isCase()
方法判斷一個(gè)值是否等于某一個(gè)case。
14缤谎、Import 別名
在java中使用兩個(gè)類名相同但包名不同的兩個(gè)類抒倚,像java.util.List
和 java.wt.List
,你必須使用完整的包名才能區(qū)分坷澡。Groovy中則可以使用import別名:
import java.util.List as jurist
import java.awt.List as aList
import java.awt.WindowConstants as WC
也可以靜態(tài)引入方法:
import static pkg.SomeClass.foo
foo()
15托呕、判斷是否為真
所有類型都能轉(zhuǎn)成布爾值,比如null
和void
相當(dāng)于0或者相當(dāng)于false
洋访,其他則相當(dāng)于true
镣陕,所以替換:
if (name != null && name.length > 0) {}
為
if (name) {}
在Groovy中可以在類中添加asBoolean()
方法來自定義是否為真。
16姻政、安全的取值
在java中呆抑,你要獲取某個(gè)對象的值必須要檢查是否為null
,這就造成了大量的if
語句汁展,像這樣的:
if (order != null) {
if (order.getCustomer() != null) {
if (order.getCustomer().getAddress() != null) {
System.out.println(order.getCustomer().getAddress());
}
}
}
Groovy中可以使用鹊碍?.
安全的取值:
println order?.customer?.address
17、斷言
檢查方法傳入的參數(shù)是否為空食绿,你可以使用assert
來檢查:
def check(String name) {
// name non-null and non-empty according to Groovy Truth
assert name
// safe navigation + Groovy Truth to check
assert name?.size() > 3
}
18侈咕、三目運(yùn)算符
三目運(yùn)算符通常用來給定默認(rèn)值,我們經(jīng)常這樣寫:
def result = name != null ? name : "Unknown"
多虧了Groovy的真值器紧,空值檢查可以簡化為'name'耀销,并且可以省略?
和:
之間的變量:
def result = name ?: "Unknown"
19铲汪、捕獲任何異常
如果你實(shí)在不想關(guān)心try
塊里拋出何種異常熊尉,你可以簡單的捕獲所有異常,并且可以省略異常類型:
try {
// ...
} catch (Exception t) {
// something bad happens
}
省略異常類型:
try {
// ...
} catch (any) {
// something bad happens
}
這里的any并不包括Throwable
掌腰,如果你真想捕獲everything狰住,你必須明確的標(biāo)明你想捕獲Throwable