閉包本質(zhì)是一段匿名的代碼塊,如是:{ -> } ; 閉包是groovy.lang.Closure類型,因此可以作為參數(shù)傳入方法,甚至閉包。 同時(shí)閉包也是一個方法,沒有與之關(guān)聯(lián)的類;因此,其可以有參數(shù)和返回值(其實(shí)還可以返回一個閉包)。 閉包總是返回代碼塊的最后一條語句,return關(guān)鍵字是可選的。閉包的方法體代碼調(diào)用時(shí)才執(zhí)行。
這個閉包帶有一個參數(shù),把參數(shù)乘以2并打印出來,符合->后面的為閉包體。 然后把閉包作為參數(shù)傳遞給其他方法,示例代碼如下:
def doubling = {arg1 -> PRintln arg1*2 }println(doubling(5)) -- result is 10上面代碼也可以簡化,默認(rèn)閉包只有一個參數(shù)可以省略,用關(guān)鍵字it代替。
def doubling = { println it*2 }利用閉包可以寫出更優(yōu)雅或簡潔的代碼,閉包通常包含較少的代碼,且容易重用。
grovvy常用的接受閉包的方法有each、collect、find等。 [1,2,3,4].each( println it) – print 2,4,6,8
each方法在Groovy JDK中的java.lang.Object中,其參數(shù)為閉包,實(shí)現(xiàn)對集合的每個成員做確切的功能。上面代碼對應(yīng)的java代碼如下:
List<Integer> list = Arrays.asList(1,2,3);for (Integer it :list) { System.out.println(it);}特別是一些資源使用前需要打開,最后需要關(guān)閉(如文件,jdbc等),我們定義一個ExpensiveResource類。
class ExpensiveResource { def open() { println 'opened!' } def writeData(data) { println "data written! $data" } def close(){ println 'closed!'}}為了使用這個類,代碼如下:
def e = new ExpensiveResource()try { e.open() println e.data} finally { e.close()}每次使用該資源是,open和close方法都必須被調(diào)用,使用閉包重構(gòu)。
def safeResource(Closure closure) {def resource = new ExpensiveResource()try { resource.open() closure(resource)} finally { resource?.close()}}safeResource { it -> it.writeData('hello world!') }safeResource 方法接受閉包,封裝資源管理代碼,分離調(diào)用代碼,使意圖更清晰。
groovy采用了類似方法處理文件訪問。通過閉包自動實(shí)現(xiàn)了打開、關(guān)閉、異常處理等場景。
curry方法只需要一個參數(shù),從左到右綁定至參數(shù)列表,只有左邊的參數(shù)有用。
下面的閉包實(shí)現(xiàn)過濾list的元素。
def filterList = { filter, list -> list.findAll(filter) }然后定義兩個實(shí)現(xiàn)過濾邏輯的閉包。
def even = { it % 2 == 0 }def odd = { !even(it) }最后,我們創(chuàng)建兩個新的閉包,通過在原閉包上使用curry函數(shù)。實(shí)現(xiàn)對偶數(shù)、奇數(shù)的過濾。
def evenFilterList = filterList.curry(even)def oddFilterList = filterList.curry(odd)assert [0,2,4,6,8] == evenFilterList(0..8)assert [1,3,5,7] == oddFilterList(0..8)新聞熱點(diǎn)
疑難解答