美文网首页
Groovy详解

Groovy详解

作者: mas_wang | 来源:发表于2017-08-09 14:21 被阅读0次

    一、安装:

    两种安装方式:

    直接官网下载,然后在配置中(.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

    相关文章

      网友评论

          本文标题:Groovy详解

          本文链接:https://www.haomeiwen.com/subject/yizfrxtx.html