Groovy了解

Apache Groovy是一种强大的、可选类型的动态语言,具备静态类型和静态编译功能,因为具备简洁、熟悉和易于学习的语法,Java平台旨在提升开发人员的工做效率。它能够与任何Java程序顺畅地集成,并当即向应用程序交付强大的特性,包括脚本功能、特定领域的语言创做、运行时和编译时元编程以及函数式编程(官方文档对groovy描述)。html

Groovy 开发环境安装

brew install groovy
复制代码
  • 安装完成在.bash_profile 文件中配置环境变量(MacOs)
You should set GROOVY_HOME:
  export GROOVY_HOME=/usr/local/opt/groovy/libexec
复制代码
  • 最后看看版本号是否安装成功
groovy -v

## 打印输出
Groovy Version: 3.0.4 JVM: 14.0.1 Vendor: Oracle Corporation OS: Mac OS X
复制代码

Groovy 基本认识

  • groovy 注释和 Java 同样 支持 // 和 /**/
  • groovy 语法和 kotlin 同样不须要写 ;
  • groovy 支持动态类型,定义变量可使用 def 关键字
def a = 1
def s = "test"
def int b = 1 //定义变量也能够知道类型
复制代码
  • 定义函数也无需指定参数类型和和返回值类型
def test(arg1,arg2){ //定义两个参数 arg1 arg2
     //逻辑代码
     ....
    
    // 函数最后一行为返回值 函数返回值为 int 类型
    10
}

String test2(arg1,arg2){ //指定返回值类型 String 则没必要写关键字 def
     //逻辑代码
     ....
    
    // 函数最后一行为返回值 函数返回值为 String 类型
    //函数指定返回值 则返回值必须一致
    // return 可写可不写
    return "aaa"
}

复制代码
  • 调用函数能够不带括号,可是建议仍是要带上括号,不然如何函数须要输入参数就会吧函数调用和属性混淆
//打印输出 hello
println("hello")

//能够写成
println "hello"
复制代码

Groovy 语法

Gradle Hello

  • 国际惯例,首先来看看一个语言的 hello world,新建一个 test.groovy,使用 groovy test.groovy 运行
println("hello groovy")
复制代码
  • 运行结果

groovy test.groovy

基本数据类型

  • groovy 语言全部东西都是对象,和Java同样,它也有 int,long ,boolean 这些基本数据类型,不过咱们不要显示声明,groovy会自行判变量类型,在 Groovy 代码中其实对应的是它们的包装数据类型。好比 int 对应为 Integer,long 对应为 Long。
def a = 1
def b = "hello groovy"
def c = false
def d = 10000000000000
println a.getClass().getCanonicalName()
println b.getClass().getCanonicalName()
println c.getClass().getCanonicalName()
println d.getClass().getCanonicalName()
复制代码
  • 执行结果

groovy基本数据类型执行结果

Groovy 中的容器类

  • groovy 容器类有三种,分别为为 List、Map和Range,对应到 Java 则为 ArrayList、LinkedHashMap 和对 List 的扩展

groovy List

  • List 对应由 [] 括号定义,其数据类型可使任何的对象
//随意添加各类类型对象 变量打印

def aList = [5,'string',true]
//元素变量
aList.each {
   //it是是与当前元素对应的隐式参数
    println "Item: $it"
}

//添加元素

//查找元素 find 方法
//
println(aList.find{ it > 1 })
println(aList.findAll{ it > 1 })

//删除元素

//执行结果
Item: 5
Item: string
Item: true
复制代码

groovyList操做执行结果

groovy Map

  • Map 变量由 [:] 符号定义,冒号左边是 key,右边是 Value。key 必须是字符串,value 能够是任何对 象。另外,key 能够用''或""包起来,也能够不用引号包起来
//其中的 key1 和 key2 默认被处理成字符串"key1"和"key2"
def aNewMap = [key1:"hello",key2:false]
//map 取值
println aNewMap.key1
println aNewMap['key2']
//为 map 添加新元素
aNewMap.anotherkey = "i am map"

aNewMap.each{
    println "Item: $it"
}

//执行结果
hello
false
Item: key1=hello
Item: key2=false
Item: anotherkey=i am map
复制代码

groovy Range

  • Range 由字面意思是范围,它其实为List的扩展,表明一个List 的范围,由 begin 值+两个点+end 值表示
//标识 list 至关于数学闭包 [1,5]
def mRange = 1..5

mRange.each {
    println "Item: $it"
}

//标识 list 至关于数学闭包 [1,5)
def mRange1 = 1..<5

mRange1.each {
    println "other Item: $it"
}

//获取开头结尾元素
println mRange.from
println mRange.to
复制代码

groovyRange执行结果

groovy-lang API 文档

Groovy 闭包(Closure)

  • Groovy语言的闭包,英文叫 Closure,是一种数据类型,它表明了一段可执行的代码
  • 闭包格式
//格式一 有参数
def xxx = {
params -> 
//返回值
code逻辑
} 

//格式二 无参数 不须要 ->
def xxx = {
  code 逻辑
} 
复制代码
  • 示例
//闭包是一段代码,因此须要用花括号括起来
def testClosure = {
        //箭头前面是参数定义,箭头后面是代码
String param1, int param2 ->
        //逻辑代码,闭包最后一句是返回值
    println "hello groovy,$param1,$param2"
    //也可使用 return,和 groovy 中普通函数同样
}
//闭包调用
testClosure.call("参数1",20)
testClosure("参数2",40)
//输出结果
hello groovy,参数1,20
hello groovy,参数2,40
复制代码
  • 若是闭包没定义参数的话,则隐含有一个参数 it,和 this 的做用类

似,it 表明闭包的参数,以下示例。java

def greeting = {
//隐含参数
    "Hello, $it!"
}
println greeting('groovy') == 'Hello, groovy!'
//等同于:
def greeting1 = {
        //也可写出隐含参数
    it -> "Hello, $it!"
}
println greeting1('groovy') == 'Hello, groovy!'

//输出结果 不用说确定都为 true
复制代码
  • 闭包省略括号,经常使用 doLast 函数
task hello{
    doLast ({
        //逻辑代码
        println'aaaaaa'
    })
}

//省略括号变成经常使用写法
task hello{
    doLast {
        //逻辑代码
        println'aaaaaa'
    }
}
复制代码

groovy 文件 I/O 操做

  • 对于文件的读取写入,groovy也是有 api 的,它实际上是对于本来的 Java 的 I/O 操做进行了一些封装,并加入闭包(Closure)来简化代码。新建测试文件 TestFile.txt

读文件

def testFile = new File("TestFile")

//读文件每一行 eachLine

testFile.eachLine{
    String oneLine ->
    //打印每一行内容
        println oneLine
}

//获取文件 byte 数组

def bytes = testFile.getBytes()


//获取文件输入流

def is = testFile.newInputStream()

//和Java 同样不用须要关闭
is.close

//闭包 Groovy 会自动替你 close 
targetFile.withInputStream{ ips ->
    //逻辑代码
}
复制代码

写文件

  • 将上述 TestFile 复制到 CopyFile
def copyFile = new File("CopyFile")

copyFile.withOutputStream{
    os->
        testFile.withInputStream{
            ips ->
            // << 是 groovy OutputStream 的操做符,它能够完成 InputStream 到 OutputStream 输出
                os << ips
        }
}

copyFile.eachLine{
    String oneLine ->
        println "copyFile oneLine:$oneLine"
}
复制代码

groovy复制文件内容执行结果

XML操做

  • 除了读取普通文件,groovy 也能够解析 XML 文件,它提供了一个 GPath 类来帮助解析 XML,平时使用 Gradle 可能须要读取清单文件(AndroidManifest)中一些数据
//建立 XmlSlurper 类

def xmlspr = new XmlSlurper()

//获取清单文件 file

def file = new File("AndroidManifest.xml")

//获取解析对象
//获取清单文件根元素,也就是 manifest 标签
def manifest = xmlspr.parse(file)

// 声明命名空间
//manifest.declareNamespace('android':'http://schemas.android.com/apk/res/android')
//获取包名
println manifest.'@package'

//获取 activity intent-filter

def activity = manifest.application.activity
//获取 intent-filter 设置的过滤条件 也能够此判断是否为应用程序入口 activity
activity.find{
   it.'intent-filter'.find { filter ->
       filter.action.find{
           println it.'@android:name'.text()
       }
       filter.category.find{
           println it.'@android:name'.text()
       }
   }
}
复制代码

解析清单文件执行结果

更多介绍 api 官方文档

groovy 脚本究竟是什么

  • 首先能够像Java 那样写 groovy class,新建一个groovyclass目录,而后编写GroovyClass类
package groovyclass

class GroovyClass{

    String p1;
    int p2;

    GroovyClass(p1,p2){
        this.p1 = p1
        this.p2 = p2
    }

    //和 Java 相似 若是不声明 public/private
    //等访问权限的话,Groovy 中类及其变量默认都是 public

    def printParams(){
        println "参数:$p1,$p2"
    }
}
复制代码
  • 上面代码是否是很熟悉,而在其余文件须要使用则 improt 引入,以下新建 testClass.groovy 文件
import groovyclass.GroovyClass

def g = new GroovyClass("hello",100)
g.printParams()
复制代码

groovyclass执行结果

groovy 脚本原理

  • 前面这么多例子,执行都是利用命令 groovy XXXX 命令执行 groovy 脚本文件,而 groovy 最终会变成字节码.class 基于JVM 虚拟机的运行的,则能够猜测,在变成字节码以前是否会转变成 Java 文件呢?以下再次看到文章开头的 test.groovy 文件
println("hello groovy")
复制代码
  • 对该文件执行以下命令
groovyc -d classes test.groovy
复制代码
  • groovyc 命令是 groovy 的编译命令,同时将编译以后的字节码文件复制到当前目录下的classes文件夹,获得的 class 文件以下

groovyclass文件

  • 1.由上图,首先 test.groovy 被转换成了 test 类,并继续 Script 类
  • 2.其次,使用 CallSite 类型数组分别保存类对象和 groovy脚本中编写的代码
  • 3.而后为这个类建立了静态 main 方法,并在 main 方法中动态代理调用 test 类的 run 方法
  • 4.最后 run 方法执行 groovy 脚本编写的代码
  • 到此,是否会有豁然开朗的感受,当咱们使用命令groovy XXXX执行 groovy 脚本,实际上是执行编译生成类对象的静态main方法,并在main方法中动态代理类对象执行了它的run方法来执行脚本中的逻辑。

demo

更多文章

参考

相关文章
相关标签/搜索