Groovy的学习笔记

Groovy的学习笔记

1. Groovy简介

Groovy 是一种动态语言,它和Java类似(算是Java的升级版,但是又具备脚本语言的特点),都在Java虚拟机中运行。当运行Groovy脚本时它会先被编译成Java类字节码,然后通过JVM虚拟机执行这个Java字节码类。

Groovy 是构建在JVM上的一个轻量级却强大的动态语言,它结合了Python、Ruby和Smalltalk 的许多强大的特性。

Groovy 就是用Java写的,Groovy语言与Java语法类似,Groovy代码能够与Java代码很好地结合,也能用于扩展现有代码,相对于Java,它在编写代码的灵活性上有非常明显的提升,Groovy 可以使用其他Java语言编写的库。

2. 准备工作

  1. 在官网下载压缩包:http://www.groovy-lang.org/download.html
  2. 解压本地
  3. 在Path 环境变量中添加上一步解压得到的Groovy文件的bin目录路径。
  4. 用CMD 打开命令行,执行:groovy -version,如果看到有版本信息,就代表配置成功了。

3. Groovy 语法

基本语法

1、Groovy 注释标记和Java一样,支持 // 或者 /**/

Groovy 的单行注释、多行注释、文档注释基本都和Java一样,没啥特殊的,不再细说。只有一种特殊的单行注释需要留意一下即可。如下:

#!/usr/bin/env groovy
println "hello from the shebang line"

这种注释通常是用来给UNIX系统声明允许脚本运行的类型的,一般都是固定写法,没啥讲究的。

2、**Groovy 语句可以不用分号结尾。**Groovy为了尽量减少代码的输入,确实煞费苦心。

3、单引号’’ 中的内容严格对应Java中的String,不对 $ 符号进行转义

def s1 = 'i am 100 $ dolloar'
println( s1 )

运行结果:

i am 100 $ dolloar

4、双引号“”的内容则和脚本语言的处理有点像,如果字符中有 $ 的话,则表达式先求值。

def x = 100
def s1 = "i am $x dolloar"

println( s1 )

运行结果:

i am 100 dolloar

5、三引号 ‘’‘hello world’’’ 中的字符串支持随意换行。如

def s1 = ''' a
b
c
d
'''

println(s1)

运行结果:

 a
b
c
d

6、return关键字可省略,方法的最后一句表达式可作为返回值返回(视具体情况使用,避免降低可读性)

7、类的默认作用域是public,不需要getter/setter方法

8、def 关键字定义的变量类型都是Object,任何变量,方法都能用def 定义/声明,在Groovy 中 “一切都是对象”。

9、导航操作符(?.)可帮助实现对象引用不为空时方法才会被调用(见下面的 判断是否为真)

定义变量

Groovy 中支持动态类型,即定义变量的时候可以不指定其类型。Groovy中,变量定义可以使用关键字def 。注意,虽然def不是必须的,但是为了代码清晰,建议还是使用def关键字

  • 定义一个变量
def a = 1  //定义一个整形

def b = "hello world"  //定义一个字符串

def double c = 1.0  //定义一个 double 类型,也可以指定变量类型

定义函数

无返回类型的函数定义,必须使用def关键字,最后一行代码的执行结果就是本函数的返回值

// 无参函数
def fun1(){
    
}

// 有参函数,无需指定参数类型
def fun2(def1,def2) {
    
}

如果指定了函数返回类型,则可不必加def关键字来定义函数

String fun3(){
    return "返回值"
}

其实,所谓的无返回类型的函数,估计内部都是按返回Object类型来处理的。毕竟,Groovy基于java ,且最终会转成Java Cod运行在JVM上。

Groovy 的函数里,可以不使用return xxx 来设置 xxx为函数的返回值。如果不使用 return 语句的话,则函数里最后一行代码的执行结果就是返回值

def test(){
    "helloworld"  //如果这是最后一行代码,则返回类型为String
    1000  //如果这是最后一行代码,则返回类型为Integer
}

除了每行代码不用加分号外,Groovy 中的函数调用的时候还可以不加括号

eg1:

def s1 = "helloworld"

println(s1)
//或者
println s1

eg2:

println(fun1())

println fun1()

def fun1() {
    "helloworld"
}

断言 assert

  • 断言变量为空
def s1 = null

assert s1
  • 断言变量的长度
def s2 = "abc"

assert s2.size()>3

assert s2.size()>3

​ | | |

| 3 false

​ abc

如果断言发生,断言后面的代码无法执行

循环 for

  • 方式一
for (i = 0; i < 5 ; i++) {
    println("test")
}
// groovy语法中,注意i前面不用指定int类型
  • 方式二
for (i in 0..5) {
    println("test")
}
// 这种方式也是一种循环,只不过他输出的是6个test,如果想要输出5个,有三种方式。
// 第一种
for (i in 0..<5){
    println("test")
}
// 第二种
for (i in 0..4) {
    println("test")
}
// 第三种
for (i in 1..5) {
    println("test")
}

循环 time

times 表示从0开始循环到4 结束

4.times {
    println it
}

结果:

0
1
2
3

三目运算符

Java 语法

def name
def result = name != null ? name : "abc"
println(result)

groovy 语法

def name = 'd'
def result = name?: "abc"

捕获异常

捕获所有的 Exception,有两种写法

// 第一种写法,java写法
try {
    println 5 / 0
} catch (Exception e) {
    
}
// 第二种写法,Groovy 写法
try {
    println 5 / 0 
} catch (anything) {
    
}

这里的安逸并不包括Throwable,如果你真想捕获everything,你必须明确的标明你想获取Throwable

switch

age =36
def rate
switch (age) {
    case 10..26:
    	rate = 0.05
    	break
    case 27..36:
    	rate = 0.06
    	break
    case 37..46:
    	rate = 0.07
    	break
    default:
        throw new IllegalArgumentException()
}

println(rate)

判断是否为真

Person person
// java写法
if (person != null){
    if(person.Data != null){
        println person.Data.name
    }
}
// groovy 
println person?.Data?.name

asType

asType 就是数据类型转换

// string 转成 int
def s2 = s1 as int
    
// string 转成 int
def s3 = s1.asType(Integer)

Groovy 数据类型

Groovy 中的数据类型主要分为2种

  • 一个是Java中的基本数据类型。
  • 另外一个是Groovy 中的容器类
  • 最后一个非常重要的是闭包
Java 基本类型
def boolean s1 = true

def int s2 = 100

def String s3 = "helloworld"

if (s1) {
    println("helloworld")
}
Groovy 容器

List:链表,其底层对应Java中的List接口,一般用ArrayList作为真正的实现类。

Map:键-值表,其底层对应Java中的LinkedHashMap。

Range:范围,它其实是List的一种拓展。

  • List
// 定义变量:List变量由[]定义,其元素可以是任何对象
def aList = [5,'string',false]

println(aList)

println aList[0]  //获取第1个数据
println aList[1]  //获取第2个数据
println aList[2]  //获取第3个数据
println aList[3]  //获取第四个数据

println( "集合长度:" + aList.size())

// 赋值
aList[10] = 100  //给第10个值赋值

aList<<10  //在 aList 里面添加数据

println  aList
println "集合长度:" + aList.size()

效果如下:

[5, string, false]
5
string
false
null
集合长度:3
[5, string, false, null, null, null, null, null, null, null, 100]
集合长度:11
  • map
def map = [key1: "value1", key2: "value2", key3: "value3"]

println map
// [key1:value1, key2:value2, key3:value3]

println("数据长度: " + map.size())
// 数据长度:3

println(map.keySet())
// [key1, key2, key3]

println(map.values())
// [value1, value2, value3]

println("key1的值:" + map.key1)
// key1的值:value1

println("key1的值:" + map.get("key2"))
// key1的值:value1

// 赋值
map.put("key4", "value4")

Iterator it = map.iterator()
while(it.hasNext()) {
    println "遍历map:" + it.next()
}

//遍历map: key1=value1
//遍历map: key2=value2
//遍历map: key3=value3
//遍历map: key4=value4

map.containsKey("key1")  //判断map是否包含某个key
map.containsValue("values1")  //判断map是否包含某个values

map.clear()  //清除map里面的内容

Set set =  map.keySet(); //把 map 的key值转换为set
  • range

Range 是 Groovy 对 List 的一种拓展

def range = 1..5

printLn(range)
//[1, 2, 3, 4, 5]

range.size() //长度

range.iterator() //迭代器

def s1 = range.get(1) //获取标号为1的元素

range.contains(5) //是否包含元素5

range.last() //最后一个元素

range.remove(1) //移除标号为1的元素

range.clear()  //清空列表

eg2:

def range = 1..5

println(range)
//[1,2,3,4,5]

println("第一个数据:" + range.from) //第一个数据
//第一个数据: 1

println("最后一个数据: "+range.to) //最后一个数据
//最后一个数据: 5
闭包

闭包,英文叫Closure,是Groovy中非常重要的一个数据类型或者说一种概念了。闭包,是一种数据类型,它代表了一段可执行的代码。

def aClosure = { //闭包是一段代码,所以需要用花括号括起来
    String parameter,int param2 ->  //这个箭头很关键。箭头前面是参数定义,箭头后面是代码
    println"this is code" //这是代码,最后一句是返回值。
    //也可以使用return,和Groovy中普通函数一样    
}

简而言之,Closure 的定义格式是:

def xxx = {paramters -> code}
// 或者
def xxx = {无参数,纯code}

闭包定义好后,要调用它的方法就是:

闭包对象.call(参数)

或者更像函数指针调用的方法:

闭包对象(参数)

比如:

aClosure.call("this is string",100)
// 或者
aClosure("this is string",100)

eg:

def fun1 = {
    p1 ->
    	def s = "我是一个闭包," + p1
}

println(fun1.call()) //闭包 调用方式1

println(fun1.call("我是一个参数")) //闭包 调用方式2

println(fun1("我是一个参数2"))

运行结果为:

我是一个闭包,null
我是一个闭包,我是一个参数
我是一个闭包,我是一个参数2

闭包没定义参数的话,则隐含有一个参数,这个参数名字叫it,和this的作用类似。it戴白哦闭包的参数。

def fun2 = {
    it -> "helloworld"
}

println(fun2.call())

如果在闭包定义时,采用下面这种写法,则表示闭包没有参数!如果调用fun3的时候传递参数就会报错。

def fun3 = {
    -> "helloworld"
}

println(fun3.call())

省略圆括号

def list = [1,2,3] //定义一个List
// 调用它的each,each是个函数
list.each{
    println(it)
}

/** 结果:
 * 1
 * 2
 * 3
 */

each函数调用的圆括号不见了! 在Groovy中,当函数的最后一个参数是闭包的话,可以省略圆括号。如

def fun(int a1,String b1,Closure closure) {
    closure() //调用闭包
}

那么调用的时候,就可以免括号!

fun(4,"test",{
    println"i am in closure"
})

注意,这个特点非常关键,因为以后在Gradle中经常会出现这样的代码:

task hello{
    doLast{
        println("hello world")
    }
}

省略圆括号虽然使得代码简洁,看起来更像脚本语言

Java属性

Groovy中可以像Java那样写package,然后写类。注意:如果一些属性方法不声明public /private等访问权限的话,Groovy中类及其变量默认都是public的。

运行原理

Java中,我们最熟悉的是类。但是我们在Java的一个源码文件中,不能不写class(interface或者其它…) ,而Groovy 可以像写脚本一样,把要做的事情都写在xxx.groovy中,而且可以通过groovy xxx.grouvy 直接执行这个脚本。这里面的原理是什么?

既然是基于Java的,Groovy会先把xxx.groovy中的内容转换成一个Java类。

在运行完XXX.groovy后,发现会产生一个 out 目录,在这个目录里面可以看到xxx.groovy被转换成了 .class文件。

  • 编译完成后,.groovy文件都被转换成了.class文件,每个.class文件都默认有静态 main方法。每一个脚本都会生成一个static main 函数。这样,当我们grovytest.groovy的时候,其实就是用java 去执行这个main 函数。
  • 脚本中的所有代码都会放在run 函数中。比如,print ‘Groovy world’ ,这句代码实际上是包含在run函数里的。
  • Test 继承Script 类
Script 类

在groovy 的库文件中,可以看到Script 类是一个抽象类,继承 Groovy ObjectSupport 类。

脚本变量的作用域

eg: Test.groovy文件

package groovy
def s1 = "123"
def fun1() {
    println s1
}

println fun1()

上述代码一运行就报错,错误通过out目录,查看Test.class 类,你会发现,s1变量定义在run 方法中,相当于局部变量,fun1方法自然无法访问s1。

解决方法也很简单,就是把s1 的def 去掉,代码如下:

package groovy
s1 = "123"
def fun1() {
    println s1
}

println fun1()

通过out 目录,查看Test.class类,你看发现 s1也没有被定义成Test 的成员函数,而是在run的执行过程中,将 s1作为一个属性添加到Test 实例对象中了。然后再 print s1中,先获取这个属性。但是从反编译的实际上看,s1并没有成为 Test.class的成员变量,其他脚本却无法访问s1 变量。

怎样使s1 彻彻底底变成 Test 的成员变量?

在 s1 前面加上@Field 字段

@Field s1 = "123" //s1彻彻底底变成 Test的成员变量 

JSON 操作

JsonOutput 类把对象转换成json字符串。

JsonSlurper 类把 json字符串转换成对象。

定义Person 实体类

public class Person {
    String name;
    int age;
}
对象转json、json转对象
Person person = new Person();
person.name = "xiaoming"
person.age = 18

//把对象转换为 json 字符串
def json = JsonOutput.toJson(person)

println(json)

JsonSlurper jsonSlurper = new JsonSlurper()

//把字符串转换为对象
Person person1 = jsonSlurper.parseText(json)

println(person1.name)

运行结果:

{"age":18,"name":"xiaoming"}
xiaoming
集合对象转json 、json转集合对象
Person person = new Person();
person.name = "xiaoming"
person.age = 18

Person person1 = new Person();
person.name = "xiaohong"
person.age = 20

def list = [person,person1]

//把集合对象转换为 json 字符串
def jsonArray = JsonOutput.toJson(list)

println(jsonArray)

JsonSlurper jsonSlurper = new JsonSlurper()

//把字符串转换为集合对象
List<Person> list2 = jsonSlurper.parseText(jsonArray)

println(list2.get(1).name)

运行结果:

[{"age":18,"name":"xiaoming"},{"age":20,"name":"xiaohong"}]
xiaohong
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

白居不易.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值