書接上文,咱們繼續講解Groovy的基礎語法部分java
重點講述的是switch/case邏輯和for循環數組
part1: switch/casebash
def x=1.23
def result
switch(x){
case 'foo':
result='found foo'
break
case 'bar':
result='bar'
break
case [4,5,6,'inlist']://List 由[]定義,其元素能夠是任何對象
result='list'
break
case 12..30://範圍
result='range'
break
case Integer:
result='integer'
break
case BigDecimal:
result='big decimal'
break
defalut
break
}
複製代碼
在java中switch/case只能傳入int類型、char類型 、String類型、枚舉類型,可是在groovy中的switch/case可能匹配到任何類型的數據,簡單的說能夠替換if/else數據結構
固然也能夠改造上面的代碼以下閉包
def x=1.23
def result
switch(x.class){
...
defalut
break
複製代碼
能夠經過x.class來判斷數據類型,好比是否爲Integer、Double類型的數據,至關因而java中的instance of的類型判斷框架
part2: for循環less
//對範圍進行循環
def sum=0
for (i in 0..9){
sum+=i
}
println sum
sum=0
//對List的循環 groovy中的List的寫法和Java中的數組寫法相似,List 由[]定義,其元素能夠是任何對象
for(i in [1,2,3,4,5,6,,8,9]){
sum+=i
}
println sum
sum=0
//對Map進行循環 java中須要經過獲取迭代器後進行操做,可是在groovy中已經處理過能夠省略該操做
for(i in ['lili':1,'luck':2,'xiaoming':3){
sum++i.value
}
println sum
複製代碼
因此相比Java而言,groovy中的邏輯控制看起來比Java中的要更強大,功能更豐富。函數
//閉包的定義
def clouser1={println 'Hello Groovy'}
clouser1.call() //調用閉包
clouser1()//調用閉包
複製代碼
1.2 閉包參數//閉包的參數使用
//單個參數
def clouser={String name ->println "Hello ${name}"}
clouser.call('groovy') //調用閉包
clouser(‘peter’)//調用閉包
def myname='wangwu'
clouser(myname)//調用閉包
//兩個參數,多個參數的寫法則爲在箭頭左側使用逗號分割添加想要添加的參數
def clouser2={String name,int age ->println "Hello ${name},My age is ${age}"}
clouser2(‘peter’,20)//調用閉包
//隱式參數 it
def clouser3={String name, ->println "Hello ${it}"}
clouser3(‘peter’)//調用閉包,一樣能夠輸出Hello peter
複製代碼
複製代碼
String name->println 'Hello Groovy'
複製代碼
以箭頭爲分割,箭頭以前就是閉包的參數部分,箭頭後面的就是閉包體內容,如遇到以下代碼,則表示參數爲空學習
->println 'Hello Groovy'
複製代碼
1.3 閉包返回值
Java中的方法有兩種返回類型,一種是有返回值,一種是無返回值,Groovy的函數裏,能夠不使用return xxx 來設置 xxx 爲函數返回值。若是不使用 return 語句的話,則函數裏最後一句代碼的執行結果被設置成返回值this
def getSomething(){
"getSomething return value" //若是這是最後一行代碼,則返回類型爲String
1000 //若是這是最後一行代碼,則返回類型爲 Integer
}
print getSomething() //結果:1000
複製代碼
可是在groovy閉包中必定會有返回值,若是閉包體裏面沒有return語句的時候,返回的就是null
//閉包返回值
def clouser={String name ->println "Hello ${name}"}
def myname='wangwu'
def result=clouser(myname)//調用閉包
println result//結果爲null
def clouser1={String name ->return "Hello ${name}"}
def result1=clouser1(myname)//調用閉包
println result1//結果爲Hello wangwu
複製代碼
//求指定number的階乘
//方法一 :upto
int fab(int number){
int result=1
//1是從1開始,到number,1屬於Integer類型,因此能夠直接調用
1.upto(number,{num->result*=num})
return result
}
//方法二 :downto
int fab2(int number){
int result=1
//grovvy中閉包能夠不放在括號內,能夠直接放在括號外.像下面這個寫法
number.downto(1){num->result*=num}
return result
}
//方法三 :times累加操做
int sum(int number){
int result
//times方法的參數也是閉包,閉包寫在括號外是groovy中很常見的方式.times方法的實現循環始終是從0開始的
number.times {num->result +=num}
return result
}
int x=fab(5)
println(x) //輸出結果:120
int y=fab2(5)
println(y) //輸出結果:120
int z=sum(101)//由於times方法中是小於,因此參數+1
println(z) //輸出結果:5050
//閉包傳遞參數類型及個數不知道時,須要查看源碼方法中是如何調用的
複製代碼
Q:爲何沒有使用循環,上面的方法都能實現階乘的效果?
A:由於upto、downto、times裏面的源碼實現了for循環的操做,詳見DefaultGroovyMethods源碼類中的解析
public static void upto(Number self, Number to, @ClosureParams(FirstParam.class) Closure closure) {
int self1 = self.intValue();
int to1 = to.intValue();
if (self1 > to1) {
throw new GroovyRuntimeException("The argument (" + to + ") to upto() cannot be less than the value (" + self + ") it's called on.");
} else {
for(int i = self1; i <= to1; ++i) {
closure.call(i);
}
}
}
複製代碼
public static void downto(Number self, Number to, @ClosureParams(FirstParam.class) Closure closure) {
int self1 = self.intValue();
int to1 = to.intValue();
if (self1 < to1) {
throw new GroovyRuntimeException("The argument (" + to + ") to downto() cannot be greater than the value (" + self + ") it's called on.");
} else {
for(int i = self1; i >= to1; --i) {
closure.call(i);
}
}
}
複製代碼
//times中的循環是i < size,因此須要+1
public static void times(Number self, @ClosureParams(value = SimpleType.class,options = {"int"}) Closure closure) {
int i = 0;
for(int size = self.intValue(); i < size; ++i) {
closure.call(i);
if (closure.getDirective() == 1) {
break;
}
}
}
複製代碼
2-2. 閉包與String結合使用(結合源碼進行學習)
String str='the 2 and 3 is 5'
//each遍歷
str.each {
String temp->print temp.multiply(2)
}
//輸出結果:tthhee 22 aanndd 33 iiss 55
each方法的返回值就是返回調用者的自己
print str.each {
// String temp->print temp.multiply(2)
}
//輸出結果:the 2 and 3 is 5
//find來查找符合條件的第一個直接輸出
print str.find{
String s->s.isNumber()
}
// 輸出結果:2
//findAll來查找全部,添加符合條件的內容
def list=str.findAll{
String s->s.isNumber()
}
print list.toListString() // 輸出結果:[2, 3, 5]
//字符串是否知足某種條件,查找到一個後返回true,不然是false
def result=str.any {
String s->s.isNumber()
}
print result //輸出結果:true
//字符串是否知足某種條件,查找到全部的都知足後返回true,不然是false
def result=str.every {
String s->s.isNumber()
}
print result //輸出結果:false
//collect:將字符串轉換成List的結果
def collList=str.collect {
it.toUpperCase()
}
print collList.toListString() //輸出結果:[T, H, E, , 2, , A, N, D, , 3, , I, S, , 5]
複製代碼
2-3. 閉包與數據結構的使用(在後面的數據結構的時候再進行學習)
2-4. 閉包與文件的使用(在後面學習文件的時候再進行學習)
複製代碼
def scriptClouser={
println 'script this:'+this
println 'script owner:'+owner
println 'script delegate:'+delegate
}
scriptClouser.call()
複製代碼
輸出的結果
script this:grammer@2a54a73f
script owner:grammer@2a54a73f
script delegate:grammer@2a54a73f
複製代碼
Q:嗯?從上面的代碼看,這三個輸出的結果不是都是一個東西嗎?區別在哪裏?
A:答案以下
this:在java中的代表當前類的方法或者是變量,groovy中也是如此,定標閉包定義處的類,實例或者是類自己
owner:代碼閉包定義處的類或者是對象,也就是說若是閉包中嵌套了閉包,那個owner表示的就是閉包內部的對象,而再也不是當前類
delegate:任意一個第三方對象,默認指向了owner的對象 代碼驗證下:
class Person{
//static 指向了Person
def static classClouser={
println 'classClouser this:'+this //Person
println 'classClouser owner:'+owner //classClouser
println 'classClouser delegate:'+delegate //classClouser
}
def say(){
def methodClouser={
println 'classClouser this:'+this
println 'classClouser owner:'+owner
println 'classClouser delegate:'+delegate
}
methodClouser.call()
}
}
//閉包中定義閉包
def nestClouser={
def innerClouser={
println 'classClouser this:'+this
println 'classClouser owner:'+owner
println 'classClouser delegate:'+delegate
}
innerClouser.delegate=p //修改默認的delegate,此時owner和delagate就不一致了
innerClouser.call()
}
nestClouser.call()
複製代碼
3-2 委託策略
//閉包委託策略
class Student {
String name
def pretty = { "My name is ${name}" }
String toString() { pretty.call() }
}
class Teacher{
String name
}
def stu=new Student(name:'Sarash')
def tea=new Teacher(name:'Qroovy')
println stu.toString() //結果:My name is Sarash
複製代碼
若是此時咱們須要獲取到Teacher類中的屬性,那麼要怎麼辦?能夠將代碼更改以下:
class Student {
String name
def pretty = { "My name is ${name}" }
String toString() { pretty.call() }
}
class Teacher{
String name
}
def stu=new Student(name:'Sarash')
def tea=new Teacher(name:'Qroovy')
stu.pretty.delegate=tea//修改委託
stu.pretty.resolveStrategy=Closure.DELEGATE_FIRST//更改委託策略方式
println stu.toString() ////結果:My name is Qroovy
複製代碼
在源碼中發現Closure的常見的委託策略有下面四個值
public static final int OWNER_FIRST = 0;
public static final int DELEGATE_FIRST = 1;
public static final int OWNER_ONLY = 2;
public static final int DELEGATE_ONLY = 3;
複製代碼
從源碼中可知,默認的委託策略就是OWNER_FIRST,假如此時代碼改變成以下的形式又會是什麼結果呢?
//閉包委託策略
class Student {
String name
def pretty = { "My name is ${name}" }
String toString() { pretty.call() }
}
class Teacher{
String name
}
def stu=new Student(name:'Sarash')
def tea=new Teacher(name:'Qroovy')
println stu.toString() //結果:My name is Sarash
複製代碼
若是此時咱們須要獲取到Teacher類中的屬性,那麼要怎麼辦?能夠將代碼更改以下:
class Student {
String name
def pretty = { "My name is ${name}" }
String toString() { pretty.call() }
}
class Teacher{
String name
}
def stu=new Student(name:'Sarash')
def tea=new Teacher(name:'Qroovy')
stu.pretty.delegate=tea//修改委託
stu.pretty.resolveStrategy=Closure.DELEGATE_ONLY//更改委託策略方式
println stu.toString()
複製代碼
猜測下應該是報錯,由於在策略中咱們並無發現name1這個屬性,如今驗證下結果
Caught: groovy.lang.MissingPropertyException: No such property: name for class: Teacher
Possible solutions: name1
groovy.lang.MissingPropertyException: No such property: name for class: Teacher
Possible solutions: name1
at Student$_closure1.doCall(grammer.groovy:83)
at Student$_closure1.doCall(grammer.groovy)
at Student.toString(grammer.groovy:85)
at Student$toString.call(Unknown Source)
at grammer.run(grammer.groovy:98)
複製代碼
果真,報錯也是提示name1這個屬性不在策略中,經過上面代碼的學習,咱們也算是對閉包有了一個瞭解了,關於這個委託策略,我以爲在普通的代碼中可能用的少,可是涉及到框架的時候就用的比較多了。 小夥伴們能夠經過本身修改上述代碼進行大家的猜測和驗證。