Groovy详解

2017-08-09  本文已影响0人  mas_wang

一、安装:

两种安装方式:

直接官网下载,然后在配置中(.bash_profile的PATH中)加上groovy的路径

直接在命令行brew install groovy,然后在配置中(.bash_profile的PATH中)加上groovy的路径(路径会在install 结束后提示)

验证安装成功:

命令行执行groovy -v,如果没有报错,且可以看到groovy版本,则成功。

注意安装之后要source .bash_profile或者重启terminal以让配置生效。(使用zsh用 source .zshrc)

二、groovy的运行

.groovy可以直接运行,也可以先编译为.class,再以java字节码运行(java和groovy两者完全兼容,因为他们都可以编译为.class,groovy可以看做java的简化版,代价是系统帮你做了很多操作,也就会体积更大,有时候可能会牺牲一些性能)

java与groovy运行对比:

java:

.java程序必须先javac编译为.class,然后再java运行

groovy:

(1)、groovy可以直接像脚本一样在命令行运行,如:groovy -e "println 'Hello World'"

(2)、也可以写一个.groovy文件,文件中直接写一句println “Hello World”就可以了,系统会自动为你加上缺省的所有代码,包括public class…,main…,以及缺省的包等。最后直接运行 groovy xxx.groovy

(3)、还可以写一个.groovy文件,然后groovyc xxx.groovy编译为.class文件,然后java xxx.class运行.class文件。但是实际上直接这样是会报错误: 找不到或无法加载主类,这是因为我们写的.groovy,会import一些groovy的包,通过反编译,可以看到class会extends Script类,这个时候我们需要加上这些东西的classpath,如:java -cp /usr/local/Cellar/groovy/2.4.7/libexec/embeddable/groovy-all-2.4.7.jar:. MyFirstExample(其中,:是mac中的分隔符,在windows中是;)

其中,(1)、(2)都是直接运行groovy脚本,而(3)是将groovy先编译为.class字节码文件,然后再在jvm上执行

三、groovy特征

1、groovy可以与java在代码上互换

简洁的groovy代码:

class HelloWorld {

static main(args) {

println "Hello World"

}

}

一行代码结束时不需要写;

默认为public,可以不写访问修饰符

static方法可以不定义返回类型,默认为def

方法调用的时候也可以简写

用java的格式也可以写:

publicclassHelloWorld {

publicstaticvoidmain(String[] args) {

System.out.println("Hello World")

}

}

2、groovy变量定义

def:

申明变量的时候,可以直接用def

实际上,通过反编译groovy编译之后的.class文件,发现def在编译为.class文件后,就是一个Object

一切皆对象:

groovy没有基础类型,定义的int等,实际对应的是其包装类型Integer

多个变量定义:

定义变量可以多个一起定义,如:

def (a,b) = [3, “a”]

也可以通过方法返回多个值来赋值(实际上是返回一个List),如:

def(c,d) = repeat("repeat",3)

3、groovy的循环

范围表示方式:

可以写成0..4的格式,表示[0,4]

还可以写成0..<4,表示[0,4)

4、groovy的方法

static方法可以在方法声明中没有返回值,默认会加上def

如果没有return,则以最后一行为返回值,如果最后一行没有含义,返回null

参数列表可以不指定类型,默认为def

参数可以设置默认值,设置了默认值的参数,可以不传,如:

staticrepeat(val, repeat =5, a){

for(iin0..repeat){

printlnval

}

printlna

}

调用repeat("repeat",3),这个时候,3对应的参数是a,repeat为默认值5

也可以repeat("repeat”,3,4),这个时候,3对应的是repeat,repeat为3,a为4

5、groovy的集合

定义:

可以 

def range = 0..4

也可以 

def coll = ["Groovy", "Java", "Ruby"]

添加项:

coll.add("Python")

coll << "Smalltalk"

coll[5] = "Perl"

第一、第二种方式,都会在末尾加一个值

第三种方式,如果已有该下标的值,则覆盖;如果没有,则将集合扩大到能容纳该下标,然后加上该值,中间缺省位置默认值为null,如:

def coll = ["Groovy", "Java", "Ruby"]

coll[5] = "Perl"

此时coll的值为["Groovy", "Java", “Ruby”, null, null, “Perl"]

检索:

通过下标

增加或去掉集合:

可以通过+/-来对集合进行加减操作,如:

defnumbers= [0, 1, 2, 3, 4]

printlnnumbers+ 6

printlnnumbers- [2,4]

此时输出的是:

[0, 1, 2, 3, 4, 6]

[0, 1, 3]

由此可见+/-操作是创建了一个新的实例

其它魔法方法:

join():

defnumbers= [1,2,3,4,3,2,1]

printlnnumbers.join(",")

输出为:1,2,3,4,3,2,1

count():

defnumbers= [1,2,3,4,3,2,1]

printlnnumbers.count(3)

输出为:2

分布操作符(spread operator):

可以对集合每个元素都执行操作,省去迭代的操作:

coll= ["Groovy","Java","Ruby"]

println coll*.toUpperCase()

println coll

输出为:

[GROOVY, JAVA, RUBY]

[Groovy, Java, Ruby]

注意toUpperCase()也是新创建一个实例

6、groovy的映射

定义:

除了常规方式,还可以这样定义映射:

defhash= [name:"Andy","VPN-#":45]

修改与添加:

修改与添加的方式,可以直接通过.号或者[]来,如:

hash.”name” = “Mike"

也可以省略””(如果key中有-等无法识别的,不能省略),如:

hash.name= “Mike"

还可以:

hash[“name”] = “Mike”  

[]中的双引号不能省略

示例:

defhash = [name:"Andy","VPN-#":45]

printlnhash

hash.name ="Mike"

hash["VPN-#"]=46

hash.dob ="17/08/08"

printlnhash

输出为:

[name:Andy, VPN-#:45]

[name:Mike, VPN-#:46, dob:17/08/08]

四、闭包

闭包单独拿出来说,是因为groovy的闭包,是一个很重要的新概念。通过反编译groovy生成的.class文件,可以看到闭包实际上是一个class,继承自Closure类

1、创建闭包:

形如以大括号括起来的代码块,参数放在大括号开头,以→结束(其实应以[]括起来,但可省略):

defa = { vala1,vala2 ->

vala1 + vala2

}

printlna(1,"a")

输出为:1a

2、特殊情况参数简化:

如果只有一个参数,可以不定义,默认为it;it可以被手动定义,不建议在闭包中定义参数名为it,避免歧义

如果参数最后也是闭包,可以不写在()内,可以在后面以{}来定义,如:

defa = { vala1,vala2 ->

vala1 + vala2()

}

printlna(1){"a"}

如果最后有多个闭包,则{}{}连起来

如果只有闭包参数,前面的()可以省略,方法参数中是闭包的情况也可以省略()

闭包会把map键值对组装到一起作为第一个参数,如:

defb = {valb1,valb2,valb3->

valb1.x+valb1.y+valb1.z+valb2+valb3

}

printlnb(x:3,4,y:5,6,z:7)

输出为25

可以像方法一样,参数设置默认取值,调用方法的时候就可以忽略该参数

可以在参数列表最后放一个Object[],来获取任意多个参数

3、闭包提供的特殊方法:

getMaximumNumberOfParameters()方法可以用来查闭包参数个数

curry()方法可以重载原闭包,并将一些参数赋值,如:

defd = {vald1,vald2,vald3->

vald1+vald2+vald3

}

defe=d.curry(1)

printlne(2,3)

输出为6

4、闭包可以迭代

5、闭包的委托策略:

三个关键字:

this表示定义闭包的外围类。

owner表示定义闭包的直接外围对象,可以是类或者闭包。

delegate表示一个用于处理方法调用和属性处理的第三方类。

this关键字用来获取闭包的外围类

owner与this不同的是,它如果在另一个闭包中定义,则指向定义它的闭包(实际上,闭包也是一个类,可以理解this忽略了闭包)

delegate默认与owner一样,但可以手动指定,指定之后,闭包中没有拥有者的参数会从delegate中获取,如:

deff = {

valf1+valf2+valf3

}

deffv = [valf1:1,valf2:2,valf3:3]

f.delegate=fv

printlnf()

输出为:6

6、delegate策略:

Closure.OWNER_FIRST这是默认的策略,优先从owner中寻找属性或方法,找不到再从delegete中寻找。上面的例子就是因为在owner中没有找到name,接着在delegate中找到了name属性。

Closure.DELEGATE_FIRST与OWNER_FIRST相反。

Closure.OWNER_ONLY只在owner中寻找。

Closure.DELEGATE_ONLY只在delegate中寻找。

Closure.TO_SELF在闭包自身中寻找。

可以使用闭包的resolveStrategy属性来设置delegate策略

实际上,闭包始终会在定义闭包的方法中找有没有局部定义的变量,如果没有,才会走delegate策略

五、参考资料

groovy官方文档:http://www.groovy-lang.org/closures.html

闭包语法总结:http://attis-wong-163-com.iteye.com/blog/1239819

闭包文档翻译:http://www.cnblogs.com/zqlxtt/p/5741297.html

IBM文档(整体讲的不错,但个人觉得闭包讲的不太仔细):https://www.ibm.com/developerworks/cn/education/java/j-groovy/j-groovy.html

上一篇下一篇

猜你喜欢

热点阅读