初识Groovy

Groovy概述

Groovy是Java平台上设计的面向对象编程语言。这门动态语言拥有类似Python、Ruby和Smalltalk中的一些特性,可以作为Java平台的脚本语言使用。

Groovy的语法与Java非常相似,以至于多数的Java代码也是正确的Groovy代码。Groovy代码动态的被编译器转换成Java字节码。由于其运行在JVM上的特性,Groovy可以使用其他Java语言编写的库。

安装

通过Homebrew安装:

1
brew install groovy

安装结束后,测试一下:

1
groovy -version

上面为Mac OS X上的安装方法,其他平台的安装方式请参考 groovy install

我们新建一个例子,命名test.groovy,里面输入这样一句话:

1
printlin "hellow word"

在终端上执行这个文件:

1
groovy test.groovy

结果:

如果我们用java来打印这段话,代码是这样的:

1
2
3
4
5
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World")
}
}

对比一下,groovy是不是简单太多了

基本语法

Groovy中支持动态类型,变量定义可以使用关键字def,即定义变量的时候可以不指定其类型。groovy会根据’=’右边的类型自动判断,比如我们定义一个变量value

1
2
def value = "hello,groovy" //结尾没有分号
println value.class //输入value的类型

输出是

1
class java.lang.String

继续赋值

1
2
3
4
5
6
def value = "hello,groovy"
println value
println value.class
value = 1 //直接赋值另外一个数据类型 没有重新申明
println value
println value.class

输出是

hello,groovy
class java.lang.String
1
class java.lang.Integer

可以看出,在groovy里,我们在运行时可以改变变量的数据类型

数据类型

作为动态语言,Groovy世界中的所有事物都是对象。所以,int,boolean这些Java中的基本数据类型,在Groovy代码中其实对应的是它们的包装数据类型。比如int对应为Integer,boolean对应为Boolean

容器

groovy中容器有三种

List:链表,其底层对应Java中的List接口,一般用ArrayList作为真正的实现类。
Map:键-值表,其底层对应Java中的LinkedHashMap。
Range:范围,它其实是List的一种拓展。

List

List变量由[]定义,比如

1
2
3
4
5
6
7
8
9
10
def list = [5,'string',true] //List由[]定义,其元素可以是任何对象
```
变量存取:可以直接通过索引存取,而且不用担心索引越界。如果索引超过当前链表长度,List会自动往该索引添加元素
```java
list[5] = "hello"
list[100] = 100
println list[5]
println list[100]
println list.size

分别输出 hello,100,101

Map

java中的map

1
2
3
Map<String, String>map = new HashMap<String, String>();
map.put("name", "mary");
map.put("age","25");

groovy定义:Map由[:]定义,注意其中的冒号。冒号左边是key,右边是Value。key必须是字符串,value可以是任何对象。另外,key可以用’’或””包起来,也可以不用引号包起来

1
def map = ["name":"mary","age":25]

也可以这样写

1
def map = [name:"mary",age:25] //Groovy 映射中的键不必是 String。在这个示例中,name 看起来像一个变量,但是在幕后,Groovy 会将它变成 String。

取值也很方便

1
2
map.name
map["name"]

Range

我们先看一个用java代码实现的一个循环

1
2
3
for(int i=0;i<5;i++){
System.out.println("Hello World" + i);
}

打印5次Hello World

用groovy怎么实现呢

1
2
3
for(i=0;i<5;i++){
println "Hello World" + i
}

更快刚简洁的呢?

1
2
3
for(i in 0..4){
println "Hello World" + i
}

for(i in 1..<5){
    println "Hello World" + i
}

其中 0..41..<5就是groovy中的range

闭包

闭包,英文叫Closure,是Groovy中非常重要的一个数据类型或者说一种概念了

闭包的一些快捷写法,当闭包作为闭包或方法的最后一个参数。可以将闭包从参数圆括号中提取出来接在最后,如果闭包是唯一的一个参数,则闭包或方法参数所在的圆括号也可以省略。对于有多个闭包参数的,只要是在参数声明最后的,均可以按上述方式省略。例如

  1. 没有参数

    def closure = {  
        println "hello closure" 
    } 
    

    //大括号括起来的代码块就是一个最简单的闭包

    闭包有一个隐含的参数,这个参数名字叫it,和this的作用类似

    def closure = {      
        it -> println "hello $it" 
    } 
    

    调用

    closure("closure")
    

    两种的输出结果是一样的

  2. 有参数并且最后一个参数是闭包

    1
    2
    3
    4
    5
    6
    def closure = {
    String name ,int age,Closure cl -> //这个箭头很关键。箭头前面是参数定义,箭头后面是代码
    println "name is" + name + ", age is " + age
    cl() //这是代码,最后一句是返回值
    //也可以使用return,和Groovy中普通函数一样
    }

    调用的时候就可以将闭包从参数圆括号中提取出来接在最后

    1
    2
    3
    closure("mary",25){
    println "yes"
    }

    输出

    name is mary, age is 25
    yes
    

我们在渠道打包的时候有一段重命名apk文件的task代码

1
2
3
4
5
6
7
8
9
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName =...
output.outputFile = new File(outputFile.parent, fileName)
}
}
}

之前硬是没看懂是什么意思,现在学习了基本的groovy语法,看起来很简单嘛。

默认导入

下面这些包和类都是默认导入的,不用再显式地使用 import 语句

1
2
3
4
5
6
7
8
+ java.io.*
+ java.lang.*
+ java.math.BigDecimal
+ java.math.BigInteger
+ java.net.*
+ java.util.*
+ groovy.lang.*
+ groovy.util.*

结语

了解了基本的groovy知识后,我们应该是深入地认识到 Groovy 就是 Java,只是缺少了你过去使用的许多语法规则。Groovy 是没有类型、没有修改符、没有 return、没有 Iterator、不需要导入集合的 Java。简而言之,Groovy 就是丢掉了许多包袱的 Java。

参考