亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

Groovy編程入門攻略

2019-11-26 15:06:55
字體:
來源:轉載
供稿:網友

當一個Java開發人員加入到Groovy的開發之旅的時候,他/她經常帶著Java思想去思考,并逐步地學習Groovy,每次學習一個特性,這會讓他慢慢變得更有創造性和寫出更符合語言習慣的Groovy代碼。這篇文章的目的是引導這些開發人員去學習基本的Groovy編程風格,學習新的操作技巧,新的語言特性,例如閉包等等。這篇文章并不會詳細鋪開描述,而是給讀者一個入門的指引,并讓讀者在以后的深入學習打好基礎。如果你喜歡這篇文章,可以貢獻你的一份力量去豐富它。

無分號

C / C++ / C# / Java開發者,經常到處使用分號。盡管Groovy支持99%的java語法,有時你只需簡單的把java代碼粘貼到Groovy程序里,但是卻帶著一大堆分號。在Groovy里,分號是可選的,你可以省略他們,更常用的用法是刪除它們。

返回關鍵字 (Return) 變得可選

在Groovy的世界里面,方法的程序塊結尾可以不寫'return'關鍵字而照樣返回值。尤其是對于語句不多的方法和閉包。這樣的寫法更優美更簡潔:
 

String toString() {return"a server"}String toString() {"a server"}

但有些情況卻不那么優美,例如你使用了變量,并在兩行里面出現兩次:
 

def props() {  def m1 = [a:1, b:2]  m2 = m1.findAll { k, v -> v %2==0}  m2.c =3  m2}
在這個例子里面,或者是在最后一個表達式后面加上一個空行,抑或是顯式地加上'return'關鍵字會令代碼更有可讀性。

我自己個人習慣,有時候喜歡用return關鍵字,有時候又不喜歡,這跟個人口味有關系吧。但是,更多時候,例如在閉包里面,我更喜歡不寫return關鍵字。所以即使return關鍵字是可選的,也不會強制你不能使用它,如果你認為它會打破代碼的可讀性。


謹慎為上,然而當你使用def關鍵字定義,而并非用代替具體某一個類型去定義的方法,有時候你會驚奇的發現最后一條表達式會作為返回結果而返回。所以更多時候更推薦使用具體的類型(例如void或類型)作為返回類型。在我們上面的例子中,如果我們忘記了把m2放在最后一行并作為返回值,那么最后的一個表達式將是m2.c = 3,這樣會導致數值3作為返回值返回,而不是我們期待的結果。

形如if/else語句,try/cath語句同樣可以返回值,因為它們里面都有"最后一個表達式"會被返回。
 

def foo(n) {  if(n ==1) {    "Roshan"  }else{    "Dawrani"  }} assertfoo(1) =="Roshan"assertfoo(2) =="Dawrani"

Def 和 類型

當我們討論def和類型,我經常會發現一些開發人員既用'def'又用類型。但是'def'在這里是多余的。所以,大家要做一個選擇,要不用'def', 要不就用類型。

所以不要寫出如下的代碼:
 

def String name = "Guillaume"

可以寫成
 

String name ="Guillaume"

當我們在Groovy里面使用def,真正的類型是Object(所以你可以向用def定義的變量,賦值任何的對象,并且,當一個方法是用def作為返回值的時候,可以以任何對象類型作而返回)。

當一個方法未聲明變量類型,你可以使用def,但是這不是必須的,所以可以省略他,所以可以代替下面的語句:
 

void doSomething(def param1, def param2) { }

推薦:
 

void doSomething(param1, param2) { }

但是,就如我們在文章末尾提到的,我們更推薦為方法的參數指定類型。這樣可以幫助提高代碼的可讀性,也可以幫助IDE工具使代碼完整,或者利用Groovy的靜態類型檢查或靜態編譯功能。

另外一個def多余的地方是定義構造函數,應避免使用:
 

class MyClass {  def MyClass() {}}

應去掉 構造函數前的'def':
 

classMyClass {  MyClass() {}}

默認的Public

默認情況,Groovy會認為類和方法是定義為'public'的。所以你不需要顯式的聲明public。當需要聲明為非public的時候,你需要顯式的指定修飾符。

所以避免如下寫法:
 

public class Server {  public String toString() {return "a server"}}

推薦使用如下簡潔的寫法
 

class Server {  String toString() {"a server"}}

你可能會關心包范圍內的可訪問性問題。事實上,Groovy允許省略public, 是因為這個包范圍里面默認情況下是不支持public,但是事實上有另外一個Groovy注釋語法去實現可訪問性:
 

class Server {  @Package ScopeCluster cluster}

省略圓括號

Groovy允許你在頂級表達式中省略圓括號,例如println語句:
 

println"Hello"method a, b

對比:
 

println("Hello")method(a, b)

當方法的最后一個參數是閉包的時候,例如使用Groovy的'each'迭代機制,你可以把閉包放在括號之外,甚至省略括號:
 

list.each( { println it } )list.each(){ println it }list.each { println it }

通常我們推薦使用上面第三種寫法,它顯得更自然,因為沒有圓括號是多么的多余!

但是Groovy在某些情況并不允許你去掉圓括號。就像我之前說的,頂級表達式可以省略,但是嵌套的方法或者賦值表達式的右邊,你卻不能省略:
 

def foo(n) { n }

 

println foo1// 錯誤寫法def m = foo1


類,一級公民

在Groovy里面,.class后綴是不需要的,有點像Java的instanceof。

例如:
 

connection.doPost(BASE_URI +"/modify.hqu", params, ResourcesResponse.class)

下面我們使用GString,并使用第一類公民:
 

connection.doPost("${BASE_URI}/modify.hqu", params, ResourcesResponse)

Getters和Setters

在Groovy的世界里,getters和setters就是我們常說的"屬性",Groovy提供一個注釋語法捷徑給我們去訪問或給屬性賦值。摒棄java方式的getters/setters,你可以使用注釋語法:
 

resourceGroup.getResourcePrototype().getName() == SERVER_TYPE_NAMEresourceGroup.resourcePrototype.name == SERVER_TYPE_NAME resourcePrototype.setName("something")resourcePrototype.name = "something"

當你用Groovy寫beans的時候,我們通常叫做POGOs(普通Groovy對象),你不需要自己創建屬性,和getters/setters方法,而是留給Groovy編譯器來完成。

所以,不再需要這樣去寫:
 

class Person {  private String name  String getName() {returnname }  void setName(String name) {this.name = name }}

而是:
 

class Person {  String name}

就如你看到的,一個簡潔的"屬性"并不帶任何的訪問修飾符,會讓Groovy編譯器為你自動生成一個私有的屬性和getter和setter方法。

當你在Java中使用這樣一個POGOs對象,getter和setter方法其實是存在的,當然跟正常的寫法無異。

雖然編譯器可以創建getter/setter方法,但是當你需要在這方法里面增加一些特殊的邏輯或者跟默認的getter/setter方法不一樣,你可以自己去定義它,編譯器自動會選擇你的邏輯代替默認邏輯。

用命名參數和默認構造器初始化beans

有這樣一個bean:
 

class Server {  String name  Cluster cluster}

為避免像下面這樣的麻煩:
 

def server =newServer()server.name ="Obelix"server.cluster = aCluster

你可以使用命名參數和默認構造器(首先會調用構造器,然后依次調用setter方法):
 

def server =newServer(name:"Obelix", cluster: aCluster)

在同一個bean里面使用with()語法處理重復操作

默認構造器中,命名參數在創建新的實例時是一件十分有趣的事情。但是當你需要更新一個實例時,你是否需要重復地在變量前重復敲打'server'這個前綴呢?答案是否定的,因為多虧了with()語句,Groovy會自動為你填上:
 

server.name = application.nameserver.status = statusserver.sessionCount =3server.start()server.stop()

對比:
 

server.with {  name = application.name  status = status  sessionCount =3  start()  stop()}

equals 和 ==

Java世界里,==就相當于Groovy里面的is()方法,另外Groovy的==就是聰明的equal()方法!

當你需要比較對象的引用的時候,你應該使用Groovy的==,因為他會幫你避開NullPointerException,而你就不需要關心操作符的左側或右側是否為null。

不應該這樣寫:
 

status !=null&& status.equals(ControlConstants.STATUS_COMPLETED)

而是:
 

status == ControlConstants.STATUS_COMPLETED


GStrings ()

我們經常再JAVA里面使用string和變量連接,并使用大量的雙引號,加號,還有/n字符去創建新的一行。而使用插值字符串(在Groovy里面叫做GStrings),可以簡化我們的代碼寫法:
 

throw new Exception("Unable to convert resource: "+ resource)

對比:
 
throw new Exception("Unable to convert resource: ${resource}")
在花括號里面,你可以放任何的表達式,而不單單是變量。對于簡單的變量,或者變量屬性,你甚至可以丟掉花括號:
 
throw new Exception("Unable to convert resource: $resource")
你甚至可以通過閉包注釋(${-> resource})對表達式進行延遲計算。當GString變量強制轉換為String變量的時候,它會自動計算閉包的值,并通過調用toString()方法作為返回值。例如:
 

int i =3 def s1 ="i's value is: ${i}"def s2 ="i's value is: ${-> i}" i++ asserts1 =="i's value is: 3"http:// 預先計算,在創建的時候賦值asserts2 =="i's value is: 4"http:// 延遲計算,使用最新的變量值

在Java里面,字符串連接是十分的累贅:
 

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}")

或者使用三個雙引號實現多行文本:
 

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)}""")

另外,你也可以使用.stripIndent()函數實現刪除多行文本里面的左側多余空格。


同時請注意Groovy里面單引號和雙引號的區別:單引號通常用來創建Java字符串,不帶任何的插值變量,而雙引號可以創建Java字符串,也可以用來創建帶插值變量的GStrings。

對于多行字符串,你可以使用三個引號:例如在GStrings變量使用三個雙引號,在簡單的String變量中使用三個單引號。

如果你需要寫正則表達式,你必須使用斜杠字符標記:
 

assert"foooo/baaaaar"==~ /fo+//ba+r/

斜杠標記的好處是,你不需要寫兩個反斜杠去做轉義,讓正則表達式更簡潔。

最后但并非不重要,請使用單引號去定義字符常量,使用雙引號定義需要使用插值函數的字符串。


原生的數據結構語法

Groovy對數據結構提供原生語法,例如列表,映射,正則表達式或者一個范圍內的數值。請在你的Groovy程序中好好使用它們。

以下是一些例子是使用那些原生數據結構的:
 

def list = [1,4,6,9] // 默認情況下,鍵是字符的,所以沒必要用引號括著它們// 你可以使用with()包含著鍵,例如使用[(狀態變量):狀態名],利用變量或對象作為鍵def map = [CA:'California', MI:'Michigan'] def range =10..20def pattern = ~/fo*/ // 等同于 add()list <<5 // 調用 contains()assert4in listassert5in listassert15in range // 下標符號assertlist[1] ==4 // 增加鍵值對map << [WA:'Washington']// 下標符號assertmap['CA'] =='California'// 屬性assertmap.WA =='Washington' // 使用正則表達式匹配字符串assert'foo'=~ pattern

 

Grovvy 開發工具

我們來繼續說說數據結構,當你需要迭代集合,Groovy提供非常豐富的方法,裝飾java的核心數據結構,例如each{}, find{}, findAll{}, every{}, collect{}, inject{}.這些方法給編程語言增加了些樂趣,同時幫助我們更輕松的設計復雜的算法。通過裝飾器,大量的新方法已應用于java的各種類型,這得得益于語言得的的動態特性。你可以查找更多的使用在字符串,文件,流,集合或者其他的方法:

http://groovy.codehaus.org/groovy-jdk/

switch的力量

Groovy的switch比C語言家族的更強大,因為它們通常只接收基本數據類型和。而Groovy的switch可以接受豐富的數據類型: 
 

def x =1.23def result =""switch(x) {  case"foo": result ="found foo"  // lets fall through  case"bar": result +="bar"  case[4,5,6,'in List']:    result ="list"    break  case 12..30:    result ="range"    break  case Integer:    result ="integer"    break  case Number:    result ="number"    break  default: result ="default"}assert result =="number"

通常情況,使用isCase()方法可以判斷一個數值是否為大小寫。

別名導入 Import aliasing

Java,中當要使用來自兩個不同包的同名class時,如

java.util.List 和 java.awt.List, 你能導入其中的一個類,而另一個你就不得不給其有效的重命名了.

還有時候我們在代碼中經常使用一個名字非常長的類,使得整個代碼變得臃腫不堪.

為了改善這些狀況, Groovy 提供了別名導入的特性:
 

importjava.util.List as juListimportjava.awt.List as aList

 
importjava.awt.WindowConstants as WC   //import的時候 用 as 設置一個別名
當然也可以靜態的導入某個方法:
 

import static pkg.SomeClass.foofoo()


Groovy 的真值體系

在groovy中所有對象都可以被強制轉為為一個boolean值,即: null, void 或空值 都 會視為 false, 其他的都視為 true.

所以不要再寫 這種代碼了:if (name != null && name.length > 0) {} 改為: if (name) {}

對于集合和其他數據類型同樣適用.

因此,你可以在 諸如while(), if(), 三目運算符,Elvis 運算符(下面會講)等等的判斷條件中使用這種簡單的方式.
更強悍的是可以給你的 類 添加 asBoolean() 方法,從而定制你這個類的真值的。

安全的操作對象圖(嵌套的對象) Safe graph navigation

Groovy支持使用 . 操作符來安全的操作一個對象圖.
Java中如果你對一個對象圖中的某個節點感興趣,想檢查其是否為null的時候,經常會寫出復雜的if嵌代碼,如下:
 

if(order !=null) { //1  if(order.getCustomer() !=null) { //2    if(order.getCustomer().getAddress() !=null) { //3      System.out.println(order.getCustomer().getAddress());    }  }}

而使用Groovy的安全操作符 ?. 可以講上述代碼簡化為:
 

println order?.customer?.address

太精妙了。

操作連上 每個?.操作符前面的元素都會做Null檢查,如果為null則拋出 NullPointerException 并且返回 一個 null值

斷言 Assert

要檢查參數、返回值等,你可以使用 assert 語句。

和 Java 的 assert 對比,Groovy 的 assert 無需單獨激活。
 

def check(String name) {  // name non-null and non-empty according to Groovy Truth  assertname  // safe navigation + Groovy Truth to check  assertname?.size() >3}

你將注意到 Groovy 的 Power Assert 語句提供更好的輸出,包括每個子表達式斷言時不同值的圖形化視圖。

Elvis (埃爾維斯)  ?:  操作符給變量賦默認值

?: 是一個非常方便的給變量 賦 默認值的操作符,他是三目運算符(xx? a:b)的簡寫.
我們經常寫如下三目運算代碼:
 

def result = name !=null? name :"Unknown"http://如果name為null時給'Unknown'的默認值,否則用原name的值

感謝Groovy的真值體系,null的檢查可簡單直接的通過 ‘name'來判斷,null 會被轉成 false.
再深入一點,既然總得返回'name',那在三目操作運算符中重復輸入name兩次就顯得累贅了,可以將問號和冒號之間輸入的重復變量移除,于是就成了Elvis操作符,如下:
 

def result = name ?:"Unknown"  //如果判斷name為 false 則取 "Unknown",否則 取name之值<span></span>


捕捉任何異常

如果你真的不在乎在一個try代碼塊中拋出的異常,groovy中可以簡單的catch所有這些異常,并忽略其異常類型. 所以以后像這種捕捉異常的代碼:
 

try{  // ...}catch(Throwable t) {  // something bad happens}

可以寫成捕捉任意異常 ('any' or 'all', 或者其他你認為是"任意"的單詞):
 

try{  // ...}catch(any) {  // something bad happens}


可選類型 建議

最后我將討論一下何時和怎樣使用 '可選類型' 這個特性.
Groovy讓你自己來決定是 顯示使用強類型 還是 使用def 關鍵字 來申明你要的東西,那么怎么決定呢?

我有個相當簡單的經驗法則:

當你寫的代碼將會被作為公共API給別人使用時,你應當總是使用強類型的申明。

這將使得: 接口約定更加明確,避免可能的錯誤類型參數的傳遞,有利于提供更易讀的文檔,在編輯如:僅你能使用的私有方法時,強制類型 會有利于IDE的代碼自動完成功能,或使IDE更容易推斷對象的類型,然后你就能更加自如的決定是否使用明確的類型了

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
57pao成人永久免费视频| 一夜七次郎国产精品亚洲| 中文字幕不卡在线视频极品| 国产精品美腿一区在线看| 欧美另类交人妖| 亚洲精品国产拍免费91在线| 欧美性色视频在线| 国产精品久久99久久| 欧美国产亚洲精品久久久8v| 尤物yw午夜国产精品视频| 色妞在线综合亚洲欧美| 一本色道久久88亚洲综合88| 久久久人成影片一区二区三区观看| 欧美日韩人人澡狠狠躁视频| 亚洲国产精品推荐| 欧美大片在线影院| 亚洲片国产一区一级在线观看| 5566成人精品视频免费| 欧美激情一级精品国产| 亚洲国产高清自拍| 国产精品激情av电影在线观看| 日韩欧中文字幕| 国产精品日韩在线一区| 日产日韩在线亚洲欧美| 国产91成人在在线播放| 久久免费福利视频| 国产亚洲精品美女久久久久| 成人网欧美在线视频| 国产九九精品视频| 亚洲欧洲国产一区| 亚洲最大的网站| 久久精品视频中文字幕| 久久久精品免费视频| 欧美贵妇videos办公室| 成人av色在线观看| 欧美性黄网官网| 国产一区二区三区毛片| 国产精品高潮呻吟久久av黑人| 91热精品视频| 日韩av手机在线观看| 日本免费久久高清视频| 国产精品www色诱视频| 欧美人在线观看| 日韩av不卡在线| 中文字幕v亚洲ⅴv天堂| 隔壁老王国产在线精品| 亚洲精品永久免费精品| 欧美日韩午夜视频在线观看| 国产精品激情av电影在线观看| 日本精品性网站在线观看| 成人国产亚洲精品a区天堂华泰| 国产精品老牛影院在线观看| 97在线观看免费高清| 欧美日韩免费在线| 国产精品www色诱视频| 在线日韩日本国产亚洲| 第一福利永久视频精品| 伊人久久大香线蕉av一区二区| 国产精品入口夜色视频大尺度| 亚洲第一级黄色片| 热re99久久精品国产66热| 欧美另类第一页| 亚洲精品日韩在线| 国产精品91久久久久久| 清纯唯美日韩制服另类| 日韩经典中文字幕| 国产欧美韩国高清| 国外成人在线直播| 91精品国产自产在线| 国产精品九九九| 美女av一区二区三区| 日韩中文字幕免费| 成人国产精品久久久| 人人澡人人澡人人看欧美| 欧洲美女免费图片一区| 91产国在线观看动作片喷水| 黑人与娇小精品av专区| 琪琪亚洲精品午夜在线| 欧美香蕉大胸在线视频观看| 红桃视频成人在线观看| 亚洲精品动漫100p| 欧美一级bbbbb性bbbb喷潮片| 日本午夜在线亚洲.国产| 亚洲高清一区二| 午夜精品久久久久久久久久久久| 亚洲最大的网站| 欧美日韩亚洲一区二区| 亚洲乱码国产乱码精品精| 欧美中文字幕第一页| 日韩美女免费观看| 久久久99久久精品女同性| 国产91在线视频| 欧美精品精品精品精品免费| 亚洲精品久久久久久久久久久| 国产精品福利在线| 国产精品视频午夜| 亚洲人线精品午夜| 国语自产精品视频在线看一大j8| 亚洲一区二区三区毛片| 亚洲免费伊人电影在线观看av| 91免费人成网站在线观看18| 日韩欧美中文字幕在线观看| 亚洲精品在线不卡| 国产亚洲人成网站在线观看| 久久这里有精品| 精品久久中文字幕| 日韩欧美在线视频免费观看| 欧美高跟鞋交xxxxhd| 永久免费看mv网站入口亚洲| 日韩欧美国产高清91| 91亚洲国产成人精品性色| 久久综合网hezyo| 一区二区三区 在线观看视| 日韩中文av在线| 91精品久久久久久久久中文字幕| 色樱桃影院亚洲精品影院| 欧美怡红院视频一区二区三区| 欧美裸体视频网站| 日本欧美黄网站| 久久6精品影院| 日韩高清电影好看的电视剧电影| 欧美另类99xxxxx| 日韩美女福利视频| 亚洲欧美综合精品久久成人| 亚洲一区二区免费| xxxx性欧美| 精品国产一区av| 国产精品网站入口| 最新亚洲国产精品| 国产精品九九久久久久久久| 欧美激情a∨在线视频播放| 日韩亚洲欧美中文高清在线| 日韩久久免费视频| www.亚洲人.com| 亚洲精品aⅴ中文字幕乱码| 亚洲精品一区二区三区婷婷月| 欧美激情免费在线| 久久久久国产一区二区三区| 久久在线免费观看视频| 欧美精品在线第一页| 久久精品成人欧美大片古装| 永久免费看mv网站入口亚洲| 欧美性受xxx| 国产日韩欧美在线观看| 欧美性高潮床叫视频| 性欧美办公室18xxxxhd| 欧美性xxxx极品hd满灌| 国产免费久久av| 精品久久久国产| 91av在线播放| 美日韩在线视频| 欧美一区二区三区免费观看| 久久久久久国产精品久久| 国产精品男人的天堂| 91在线免费观看网站| 中文字幕不卡在线视频极品| 久久久av一区| 狠狠做深爱婷婷久久综合一区| 国产免费成人av| 久久成人这里只有精品| 宅男66日本亚洲欧美视频| 日本一区二三区好的精华液| 国产欧美一区二区三区在线| 91高清免费在线观看|