groovy一些知識點

一、代碼塊
在代碼塊中用def關鍵字定義的變量不能在外部訪問,如:

try{
def msg="Hello,world!";
}
//pringln msg;


如果運行最後一行"println msg;",則會報錯。

但是,在代碼塊中沒有用def關鍵字聲明的變量,就可以在外部訪問,如:

try{
msg="Hello,world!";
}
println msg;


已經使用def定義的變量,不能再次用def定義:
def a=10;
//def a=20;



代碼塊是可以嵌套的:

try{
try{
try{
println "Hello,world!";
}
}
}


二、閉包
閉包是可以引用外部上下文環境的一系列語句。可以將閉包賦予一個變量,並在稍後執行。

每個閉包都有一個返回值,默認的返回值就是該閉包中最後一行語句的結果

閉包可以訪問外部的變量
def x=1;

def b={
x*2;//閉包可以訪問外部的變量
}


將閉包賦予一個變量將記住該閉包創建時的上下文環境,即使運行時已經超出了原來的作用域:
def c;

try{
def m=10;
c={m};
}

println c();

在此處調用c(),即使已經超出了block的作用域,但仍能輸出m的值


將一個閉包放入另一個閉包,可以創建它的兩個實例:

c={e={"Hello,World";};e;}
v1=c();
v2=c();
println v1==v2//在此得出false,說明c()返回了不同的實例


可以在定義閉包時聲明一些參數,之後在調用閉包時將這些參數值傳入閉包:

c={n-> println "Parameter="+n;}

c(10);


可以利用參數將信息從包內導出,也就是所謂的“輸出參數”

c={o,p-> o<<p};
x=[];
c(x,1);
c(x,2);
c(x,3);
println x;


在閉包中,總是可以用到一個叫做it的變量,如果沒有顯式的定義參數,則可以用it來引用

[quote]c={"Parameter=${it}"};
println c(10);[/quote]

如果沒有傳入任何參數,it仍然存在,但是爲null

閉包的參數不能使用作用域中已存在變量的名字,除了隱式變量it:
def it=10;

c={it*it};

println c(5);//在此,隱式變量it仍然引用參數5,而非外部定義的10

參數在調用閉包時可以被命名。這些被命名的參數將被組裝進一個Map,並指定給閉包的第一個參數:
def x={a,b,c->a.m+a.n+a.o-b+c;};

println x(m:10,5,n:15,6,o:20);


在調用閉包x的時候,參數m:10,n:15,o:20被組裝進Map賦予形參a,5、6按順序分別賦予形參b和c,結果是46。

我們可以在閉包內部和外部查詢參數的個數:


def c={a,b,c->getMaximumNumberOfParameters();}

println c(1,2,3);

println c.getMaximumNumberOfParameters();


調用閉包的時候,可以對最後的一個或幾個參數應用默認值:

def c={a,b=2,c=3->a+b+c;};

println c(1);


結果輸出6

一個閉包可以在最後一個參數前添加Object[]前綴來創建可變長度的參數:

def c={a,Object[] b->a+b[0]+b[1];}

println c(1,2,3);


我們可以使用一個list參數調用閉包。如果閉包沒有定義一個list類型的參數,則此參數將作爲分解的參數傳入閉包:

def c={a,b,c->a+b+c};

println c([1,2,3]);


閉包可以通過將第一個或前幾個參數固化爲常量,使用curry方法進行拷貝:

def c={a,b,c->a+b+c};

def d=c.curry(1);//拷貝閉包c,並將第一個參數a固化爲常量1

println d(2,3);//調用閉包d,只需要給出剩餘的參數。實際使用的參數仍然是1,2,3


在閉包中,可以結合使用curry和不定長度參數:

def c={a,Object[] b->b.each({m->a=a+m;});a;};

def d=c.curry(1);

def e=d.curry(2,3);//實際參數爲1,[2,3]

def f=e.curry(4);//實際參數爲1,[2,3,4]

println f(5);//實際參數爲1,[2,3,4,5]


閉包可以遞歸調用

三、函數

首先,必須使用def關鍵字定義函數,函數也不能嵌套使用;

其次,函數不能訪問在外部通過def定義的變量:

def c=10;

def f(){
println c;//編譯通過
}

//f();//運行時報錯


還可以使用特殊的語法標記&將函數賦予新的命名:

def f(){
println "Hello,world!";
}

def s=this.&f;

s();


函數可以後參數,包括輸入參數和輸出參數;

如果兩個函數的擁有不同個數的未指定類型的參數,則可以使用相同的名稱

def f(a){
println a*a;
}

def f(a,b){
println a*b;
}

f(10);

f(5,10)


函數可以有返回值:
1.如果有顯示地使用return關鍵字,則返回return指定的返回值,其後面的語句不再執行;
2.如果沒有顯式地使用return關鍵字,則返回函數最後一行語句的運行結果;
3.如果使用void關鍵字代替def關鍵字定義函數,則函數的返回值將爲null。

如果一個函數與一個閉包擁有相同的名稱和參數,則調用的時候將執行函數,而不是閉包:

def f(a){
return a*10;
}

def f={a->a*20};

println f(5);//輸出50而不是100

函數可以接受閉包作爲參數:

def f(a,Closure c){
c(a);
}

f(10){println "Parameter a = "+it;}


與閉包相同,函數可以爲參數指定默認值:

def f(a,b=10){
return a+b;
}

println f(5);//輸出15


函數也會將命名的參數包裝進一個Map,並賦予第一個參數:

def f(a,b){
return b+a.x+a.y;
}

println f(x:2,1,y:3);//輸出6


函數與閉包的相同之處還有,函數同樣支持不定長度的參數、分解list作爲參數,以及遞歸調用。
發佈了16 篇原創文章 · 獲贊 0 · 訪問量 2804
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章