书接上文,咱们继续讲解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这个属性不在策略中,经过上面代码的学习,咱们也算是对闭包有了一个了解了,关于这个委托策略,我以为在普通的代码中可能用的少,可是涉及到框架的时候就用的比较多了。 小伙伴们能够经过本身修改上述代码进行大家的猜测和验证。