Groovy快速入门

来源:互联网 发布:js bind()方法 编辑:程序博客网 时间:2024/06/05 08:27

Groovy简介

Groovy是基于Java平台开发的一门强大的、具有Optional类型,多功能性的动态语言,它具有静态类型和静态编译的功能。为了提高在java平台的开发效率,它的语法设计的很简洁,易学。和java无缝集成,从而使自己的项目具有强大的特性,比如脚本功能、DSL(Domain-Specific Language)语言编写,运行时和编译时元编程(meta-programming)以及函数式编程。

Groovy优势

  • 语法简洁,可读性强,并且很容易上手
  • 功能强大,具有闭包特性,自动构建,元编程,函数式编程,Optional类型以及静态编译的功能
  • 集成性强,与Java语言或者一些第三方库无缝接入
  • DSL语言编写,语法灵活,扩展性强,使项目具有高级配置与可定制的机制,可读性强的特点
  • 完整的生态系统,涉及Web开发、reactive应用,并发性、异步的库、测试框架、构建工具(Build Tools)、代码分析、GUI构建
  • 脚本测试,可以写一些简单的、可维护的测试用例,来完成自动化构建任务

安装Groovy

Groovy下载链接 
下载后,把压缩包解压到相应的位置,然后再环境变量的Path里面添加解压后的路径(到解压的bin目录下)。配置好后,然后运行groovy -v,可以看到如下图

图1.png

到这里,就安装好了。

Groovy IDE

图2.png

Hello Groovy

运行groovyconsole之后,稍等,可以看到启动的Groovy自带的编辑器。输入第一句代码:

println "Hello Groovy!"
  • 1

然后按CTR+R就可以得到如下输出

groovy> println "Hello Groovy!" Hello Groovy!
  • 1
  • 2
  • 3

或者我们save as到一个相应的位置保存为hello.groovy,然后cd到相应的目录下面,运行groovy hello.groovy,得到结果也一样,如下图

图3.png

Java&Groovy不同点

  • 默认含有import ,引入包无须在前面再申明import,比如java.io.*java.lang.*等等
  • 方法多元化(Multi-methods)Groovy的参数类型决定于代码运行时,Java正好相反,Java参数类型决定于编译时,主要用申明的类型决定。比如举个例子 
    Hello.groovy
void method(String arg){    println "this arg is string type";}void method(Object arg){    println "this arg is Object type";}Object obj = "hello Groovy";method(obj);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

输出结果为

this arg is string type
  • 1

Hello.java

public class Hello{    void method(String arg){        System.out.println("this arg is string type");    }    void method(Object arg){        System.out.println("this arg is Object type") ;    }    public static void main(String[] args){        Object obj = "hello Groovy";        Hello hello = new Hello();        hello.method(obj);    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

输出结果为

图4.png

  • Array初始化

java初始化一个Array,一般是这样

int[] array = {1,2,3};
  • 1

但是在Groovy里面{...}代表的是一个闭包(closures),所以Groovy不能和Java这样申明。我们应该这样申明

int[] array = [1,2,3]
  • 1
  • 包范围可视性

    比如一个类

    class Person{  String name}
    • 1
    • 2
    • 3

    Groovy里面,没有可视化修饰符的属性,都是公有的,并且会生成gettersetter方法。如果要私有化这个属性,可以加注解@PackageScope,如下

class Person {    @PackageScope String name}
  • 1
  • 2
  • 3
  • ARM 块 
    ARM(Automatic Resource Management)自动化资源管理,在Java7开始引入,但是Groovy不支持,所以Groovy通过闭包的形式提供了各种各样的依赖方法来替换,实现效果是一样的。比如:
Path file = Paths.get("/path/to/file");Charset charset = Charset.forName("UTF-8");try (BufferedReader reader = Files.newBufferedReader(file, charset)) {    String line;    while ((line = reader.readLine()) != null) {        System.out.println(line);    }} catch (IOException e) {    e.printStackTrace();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

可以写成:

new File('/path/to/file').eachLine('UTF-8') {   println it}
  • 1
  • 2
  • 3

或者写成和上面Java版本更像的代码:

new File('/path/to/file').withReader('UTF-8') { reader ->   reader.eachLine {       println it   }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 内部类 
    Groovy的匿名内部类和内嵌类和Java的实现方式是一样的,但是 Groovy不支持y.new X()这种实现方式,需要使用 new X(y),如下 
    Java
public class Y {    public class X {}    public X foo() {        return new X();    }    public static X createX(Y y) {        return y.new X();    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Groovy

public class Y {    public class X {}    public X foo() {        return new X()    }    public static X createX(Y y) {        return new X(y)    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • Lambda 表达式 
    Java8是支持Lambda表达式的,比如
Runnable run = () -> System.out.println("Run");list.forEach(System.out::println);
  • 1
  • 2

但是Groovy是不支持,取而代之的是使用闭包实现的一样的效果

Runnable run = { println 'run' }list.each { println it } // or list.each(this.&println)
  • 1
  • 2
  • GStrings

Java里面字符串是"xxxxx"这样的形式,但是在Groovy里面这种形式叫GString(Groovy String)或者String类型,当使用($)符号引用类型是,它会自动转换为GString类型,反之,为String类型。

  • 字符串和字符字面量 
    当使用'xxx'形式使用的时候,它的类型为字符串(String),当使用"xxx"的时候,参考上面GString说明

  • 基本类型和封装性 
    由于Groovy一切类型皆对象,所以它会自动把基本类型封装成对象,这一点和Java规范不同,比如

int im(i)//方法1void m(long l) {             println "in m(long)"}//方法2void m(Integer i) {          println "in m(Integer)"}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如果是Java,自然会去执行方法1,但是Groovy则会执行方法2

  • ==的不同

Java==指的是基本类型相等或者是对象的引用相等,但是在Groovy中,Java==含义转换为a.compareTo(b)==0,如果两边都实现了Comparable接口的话,而Groovy==的含义指的是a.equals(b),对象引用是否相等,则是使用a.is(b)

  • 转换 
    java的自动转换只能向下转换,Groovy则进行相应的扩展,具体如下

图5.png

Y 表示 Groovy 可以执行的转换。D表示的是在动态编译或显式转换时 Groovy 能够执行的转换。T 表示 Groovy 可以执行的转换,但数据被截断了。B表示装箱/拆箱操作。N表示Groovy不能实行的转换。

  • 扩展的关键字
asdefintrait
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Groovy开发套件

IO操作

Groovy提供了一些IO操作的帮助类,这里提供几个常用的API 
1.  java.io.File 
2.  java.io.InputStream 
3.  java.io.OutputStream 
4.  java.io.Reader 
5.  java.io.Writer 
6.  java.nio.file.Path

  • 读文件 
    通过Groovy读取文件很简单,举个例子,先在E:/Android/Groovy/workspace目录下创建一个read.txt文件,然后编写代码
new File('E:/Android/Groovy/workspace','read.txt').eachLine{ line ->    println line}
  • 1
  • 2
  • 3

File对象有两个参数,一个是文件的路径,一个是文件的文件名,然后eachLine方法就可以读取到文件内容

这是通过Groovy的IO方法读取的一个txt文件,
  • 1

其实,在FileAPI里面还可以查到eachLine还有很多个参数

图6.png

Groovy里面,使用IO操作,即使代码出现异常,IO读取流也会保证会被关闭。比如

def count = 0, MAXSIZE = 3new File(baseDir,"haiku.txt").withReader { reader ->    while (reader.readLine()) {        if (++count > MAXSIZE) {            throw new RuntimeException('Haiku should only have 3 verses')        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 写文件
new File('E:/Android/Groovy/workspace','write.txt') << '''Groovy is Good,Groovy is NiceGroovy is Beautiful!'''
  • 1
  • 2
  • 3

在相应的位置就可以找到write.txt,然后内容为

Groovy is Good,Groovy is NiceGroovy is Beautiful!
  • 1
  • 2
  • 3

集合

List操作
  • 取元素 
    def emptyList = []//空List 
    def list = [1,5,7,8] 
    list.get[2] = 7 
    list.getAt(2) = 7 
    list[2] = 7 
    list[-2] = 7 
    list[1..2] = [5,7] 
    list[1..<7] = [5,7]
  • 迭代元素
list.each{      println "Item: $it"}
  • 1
  • 2
  • 3
list.eachWithIndex{      item,i ->      println "$i:$item"}
  • 1
  • 2
  • 3
  • 4

Groovy映射功能,通过collect从当前集合映射到另个集合

def list = [1,5,7,8]def newList = list.collect{it.multiply(2)}.eachWithIndex{    item,i ->    println "$i:$item"}
  • 1
  • 2
  • 3
  • 4
  • 5

输出

0:21:102:143:16
  • 1
  • 2
  • 3
  • 4
  • 过滤和搜索

list.find{it>5} == 7 
list.findAll{it>5} == [7,8]

通过一个list去搜索匹配

['a','b','c','d','e'].findIndexOf{    it in ['k','e','g']} == 4
  • 1
  • 2
  • 3

['a','b','c','d','e'].indexOf('c') == 2 
['a', 'b', 'c', 'd', 'c'].indexOf('k') == -1//list不存在元素则返回-1 
['a', 'b', 'c', 'd', 'd'].lastIndexOf('c') == 4 
[1, 6, 3].every { it < 5 } == false//集合所有元素小于5则返回true 
[1, 2, 4].any { it > 3 } //集合任何一个元素大于3则返回true 
[1, 2, 3, 4, 5, 6].sum() == 21//求和 
[1, 2, 3].join('-') == '1-2-3'//加入间隔符并转换为String

[1, 2, 4].inject(3){    count ,item -> count + item    } == 10 // 注入对应的元素 3+1+2+4
  • 1
  • 2
  • 3

[1, 2, 3].max() = 3 
[1,2,3].min() = 1 
- 添加和删除元素

[1, 2, 4] << 5 == [1,2,4,5] 
[1, 2, 4] << 5 << 7 << 8 == [1, 2, 4, 5, 7, 8] 
[1, 2, 4] << [5,8] == [1, 2, 4, [5, 8]] 
[1, 2] + 3 + [4, 5] + 6 == [1, 2, 3, 4, 5, 6] 
[1, [2, 3, [4, 5], 6], 7, [8, 9]].flatten() == [1, 2, 3, 4, 5, 6, 7, 8, 9] 
['a','b','c','b','b'] - 'c' == ['a','b','b','b'] 
- 排序 
[6, 3, 9, 2, 7, 1, 5].sort() == [1, 2, 3, 5, 6, 7, 9] 
- 复制元素 
[1, 2, 3] * 3 == [1, 2, 3, 1, 2, 3, 1, 2, 3] 
[1, 2, 3].multiply(2) == [1, 2, 3, 1, 2, 3] 
Collections.nCopies(3, 'b') == ['b', 'b', 'b']

Map操作

其中Map操作和List操作的方法差不多,只不过Map是通过获取key来操作的,而List是通过index获取,这点和Java里面的集合操作是一样的

def map  = [Name:'Goach',Sex:'man',Age:'24',]map.each{    entry -> println "key:$entry.key   value:$entry.value"}map.eachWithIndex{    entry ,i -> println "$i - key:$entry.key  value:$entry.value"}map.each{    key,value ->  println "key:$key   value:$value"}map.eachWithIndex{    key,value,i ->  println "$i -key:$key   value:$value"}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

ConfigSlurper

ConfigSlurper 是Groovy里面一个读取配置文件的帮助类,和Java *.properties一样。ConfigSlurper允许使用.或者以闭包的形式配置值得作用域和任意的对象类型,比如

def config = new ConfigSlurper().parse('''        //.的形式        app.date = new Date()        app.sex = 'm'      //闭包的形式         app {             age = '23'             name = 'Goach'          }''')println "date:$config.app.date; sex:$config.app.sex;"+         "age:$config.app.age;  name:$config.app.name"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

输出为:

date:Thu Jun 08 14:15:33 CST 2017; sex:m;age:23;  name:Goach
  • 1

上面的的字符串我们也可以用文件形式读取,比如

def config = new ConfigSlurper().parse(new File("config.groovy").text)
  • 1

MOP

Groovy也具有元对象协议的特性(Meta Object Protocol,MOP),实现这个特性,有个很重要的类就是groovy.lang.GroovyObject。基本上Groovy的对象都直接或者间接的实现了它。GroovyObject有两个很重要的方法invokeMethod()getProperty(),当一个对象调用一个方法或者属性的时候,而这个方法或者属性不存在的时候,这两个方法就会被调用。比如

class Person{    def invokeMethod(String method,Object params){        println "call invokeMethod ${method}"        if(params != null){            params.each{                println "\tparams ${it}"            }        }    }    def getProperty(String property){        println "property:${property}"    }}def person = new Person()person.sayHello("hello")person.name
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

输出为

call invokeMethod sayHello    params helloproperty:name
  • 1
  • 2
  • 3

当这个方法不存在的时候,它就会进行拦截,然后智能的输出响应的对象。同时会调用methodMissing这个方法

  • 添加方法 
    当为一个类添加方法的时候,一般可以使用<<或者=运算符来添加方法,比如
class Car{    String name}Car.metaClass.run << { -> println "$name在路上跑"}def car = new Car(name:"宝马")car.run() == "宝马在路上跑"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 添加属性
Car.metaClass.speed = '120km/h'
  • 1
  • 构造函数
class Food{    String name}Food.metaClass.constructor << { String name -> new Food(name:name)}def food = new Food('apple')println "food name is ${food.name}"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 静态方法
class Book {   String title}Book.metaClass.static.create << { String title -> new Book(title:title) }def b = Book.create("The Stand")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 间接调用方法
class Person{    String name}class Action{    def sayHello(){        "Hello!"    }}def action = new Action()Person.metaClass.hello = action.&sayHellodef person = new Person()println person.hello() == "Hello!"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 动态方法名称
class Person{    String name = "Goach"}def methodName = "Lili"Person.metaClass."changeNameTo${methodName}" = {-> delegate.name = "Lili"}def person = new Person()println person.changeNameToLili() == "Lili"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Groovy更多的使用方法,例如AST转换,Grape的依赖,写一些测试用例,DSL语言以及GroovyJava里面的常用方法可以参考官网,由于篇幅的原因,入门的简单学习就暂时到此为止。

参考文献

Groovy官网 
Groovy1.6的新特性 
Groovy入门 
实战Groovy

原文地址:http://blog.csdn.net/Iamzgx/article/details/72972255

原创粉丝点击