目录

  • groovy简介
  • groovy类的基本特点
  • 在java项目中引入groovy
  • 定义变量
  • groovy中的常见类型
    • 字符串
    • 数组 、列表 list
    • 元祖 tuple
    • 映射 | 字典 | map
  • 范围运算符 ..
  • 切片
  • 方法定义、调用
  • 闭包
  • 类的定义
  • IO
    • 控制台输出
    • File类
    • 文件读
    • 文件写
    • 遍历文件树
    • 说明
  • 单元测试

groovy简介

Groovy是一种基于 JVM 的编程语言,结合了 python、ruby 和 Smalltalk 的许多强大的特性,面向对象,Groovy 可以与 Java 代码很好地结合,可以直接在groovy中写java代码,既可以用于面向对象编程,又可以用作纯粹的脚本语言。

groovy的主要特点

  • 同时支持静态、动态类型
  • 支持各种标记语言,比如原生支持xml、html
  • 支持闭包
  • 可以在groovy中直接写java代码,可以直接使用现有的java类库,相比于java,groovy更加简洁;
  • groovy语法和java非常相似,易于java开发者掌握。

groovy类的基本特点

  • 一个.groovy文件中可以包含多个public类,不要求public类的类名月文件名相同;
  • 默认访问修饰符是public,如果类、成员使用public修饰,可以缺省public;
  • 支持动态类型,不管是变量还是方法返回类型,都不需要声明类型;
  • 语句末尾的分号不是必需的,可以省略;
  • 注释和java相同。

groovy 默认会导入以下包、类,无需 import 显式导入

import java.lang.*
import java.util.*
import java.io.*
import java.net.* import java.math.BigInteger
import java.math.BigDecimalimport groovy.lang.*
import groovy.util.*

groovy在 java.lang.Object 的基础上进行了扩展,相比于java的Object类,groovy中的Object类具有更多的方法。

在java项目中引入groovy

很少直接用groovy写一整个大项目,一般是搭配java使用,用来写部分模块、服务、脚本。

pom.xml

<dependency><groupId>org.codehaus.groovy</groupId><artifactId>groovy-all</artifactId><version>3.0.9</version><type>pom</type>
</dependency>

定义变量

groovy自动导入了 java.lang,可以使用java的数据类型

//可以使用具体类型,也可以声明为 def 任意类型、动态类型int x
int y = 5def x
def y = 5

在groovy中,对于自带类型,== 相当于 equals

//true 通过
assert new String("xxx") == new String("xxx")

groovy中的常见类型

字符串

groovy的字符串可以用单引、双引、三引定义,单引中可以使用双引,双引中可以使用单引,三引中可以使用单、双引。

三引类似 html 的 <pre> 标签,可以保证内容格式不变。

//单双引
def str1 = 'hello world'
def str2 = "hello world"//三引
def str3 = '''hello world'''
def str4 = """hello world"""

模板字符串

def user = new User(1, "chy")//字符串内可以通过 ${} 引用变量,可以访问属性、调用方法
println("user: ${user}")
println("name: ${user.name}")
println("name:${user.getName()}")//直接访问对象本身或属性时,可以缺省{},调用方法时则不能缺省{}
println("user:$user")
print("name:$user.name")

双引中的 $表达式 才会被解析,单引、三引中的 $表达式 会被当做普通字符串处理。

与java不同,groovy中的字符串可通过下标直接索引

def str = "hello world"//java中可以通过 charAt() 来获取指定位置的字符,但不能直接 [n] 以数组下标方式直接操作
//groovy可以以[n] 数组下标方式来获取字符串指定位置的字符,但不能通过 [n] 来给字符串指定位置赋值
//数组则可以通过 [n] 直接取值、赋值
println str[0]//取 [0,4] 上的字符串
println(str[0..4])//先取 [0,4] 上的字符串,再将字符串反序排列
println(str[4..0])//将字符串重复指定次数,java中没有此操作
println(str * 3)

数组 、列表 list

在 groovy 中

  • 大括号是留给闭包(closure)使用的,数组、列表都使用中括号进行定义;
  • 数组、列表的元素都有序,可通过下标索引;
  • 区别:数组元素类型相同,列表元素类型可以不同。
//java中定义数组
int[] array = {1, 2, 3};//groovy中定义数组
int[] array = [1, 2, 3]//groovy中定义列表
def list = [1, 2, "zhangsan"]
//支持嵌套
def list3 = [1, 2, ["zhangsan", "lisi"]]

列表常用方法

def list1 = [1, 2]
def list2 = [3, 4]//在指定位置添加元素,index范围只能是 [0, size]
list1.add(0, "lisi")
//缺省index时默认添加到末尾
list1.add("wangwu")//add是把参数作为一个元素进行添加,参数是集合时,会整个集合作为一个元素添加
list1.add(list2)
//如果要将其它集合中的元素都添加到当前集合汇总,可以用 plus 或 + ,返回副本
list1 = list1 + list2
// list1 = list1.plus(list2)//添加是add、plus(+),移除是remove、minus(-),使用方式相同,add => remove,plus => minus//元素反序排列,返回副本
list1 = list1.reverse()//元素排序,直接修改的原list。默认自然排序,可自定义排序规则
list1.sort()

列表的遍历

def list = ["zhangsan", "lisi", "wangwu"]//传统for循环方式
for (def ele : list) {println(ele)
}
for (i in 0..<list.size()) {println(list[i])
}//lambda表达式
list.each { ele -> println(ele) }//闭包
list.forEach({ ele -> println(ele) })
list.iterator().forEachRemaining({ ele -> println(ele) })

元祖 tuple

  • tuple是一种特殊的list,和list一样元素有序、类型可以不同,可以通过下标来访问。
  • 与list的区别:不能增删、修改元素(引用类型可以修改内部属性值,但不能修改引用本身),否则会抛出 UnsupportedOperationException。
  • IDE代码提示中有 add()、remove() 之类的方法,但那是list的方法,tuple实际是不能使用的。
//Tuple 元素数量不限
def tuple = new Tuple(10, "zhangsan", true, new Person())//可以通过下标来访问
println tuple.get(0)
println tuple[0]
println tuple[0..2]//Tuple 1~9,元素最多只能为指定数量,eg. Tuple1 元素最多1个、最少0个
def tuple1 = new Tuple1(10)
println tuple1.firstdef tuple2 = new Tuple2(10, "zhangsan")
println tuple2.seconddef tuple3 = new Tuple3(10, "zhangsan", true)
println tuple3.third

映射 | 字典 | map

映射也叫作字典、map

def userInfo = ["name": "chy", "age": 20]//更新key对应的value
userInfo.name = "zhangsan"//获取key对应的value
println(userInfo.name)
println(userInfo.get("name"))

转换为实体类

def map = ["id": 1, "name": "chy"]//as转换为指定类型,也可以直接用java格式的 (Person) map
def person = map as Person

范围运算符 …

//[1,10] 总共10个数字
def range1 = 1..10//[1,10) 总共9个数字
def range2 = 1..<10//支持 降序|反序 排列
def range3 = 10..1//支持字符
def range4 = 'A'..'D'

本质是一种特殊的 list,可以使用 list 的操作方式,比如 [index] 访问指定位置的元素。

常用方法

//是否是反序排列
println(range.reverse)
println(range.isReverse())println(range.size())println(range.sum())println(range.contains(1))println(range.get(0))
//获取最小元素,包装类型
println(range.from)
println(range.getFrom())//获取最小元素,基本类型
println(range.fromInt)
println(range.getFromInt())//获取最大元素,包装类型
println(range.to)
println(range.getTo())//获取最大元素,基本类型
println(range.toInt)
println(range.getToInt())//获取首尾元素
println(range.first())
println(range.last())//子区域 [0,5]
def list = range.subList(0, 5)//注意:from、to不是range的首尾元素,而是range中最小、最大的元素

切片

arr、list、tuple、string 都可以用范围运算符进行切片

def list = [1, 2, 3, 4, 5]//[0,1]。相当于subList(),区别在于范围运算符左右都是闭合,subList()是左开右闭
def list1 = list[0..2]//[0,2)
def list2 = list.subList(0, 2)

方法定义、调用

  • 方法可以使用 private、static、final 之类的关键字修饰,缺省访问权限时,默认为 public;
  • groovy的 main 方法声明与 java 相同,只是默认就是public,缺省了关键字 public。
//显式指定类型
int sum(int a, int b) {return a + b
}//参数可以不指定类型,不指定类型时为 def
def sum(a, b) {return a + b
}//运行时会根据实参确定参数类型,可以实现函数重载
sum(1, 2)
sum("hello", " world")//默认参数:放在形参表末尾,调用时可传可不传
def sum(a, b = 0, c = 0) {return a + b + c
}sum(1)
sum(1, 2)

如果方法要给其他人使用,使用 def 有一个很大的缺点,调用者不知道参数要传什么类型、返回值要传什么类型,所以groovy常用于编写单人开发的模块、脚本,很少成为项目的主体语言。

方法调用可以缺省小括号,构造函数除外

def user = new User(1, "chy")//使用()
println(user.name)
printf("user:%s", user)//不使用()
println user
printf "user:%s", user

运行时分派:对应函数重载,groovy是以运行时实参的实际类型来进行方法调用

int method(String arg) {return 1;
}int method(Object arg) {return 2;
}//虽然实参声明为Object,但实际为String,所以实际调用的是第一个方法
Object o = "Object";
int result = method(o);

闭包

闭包(closure)是一个短的匿名代码块,使用大括号定义

//定义闭包
def closure1 = { println("xxx") }
//执行闭包中的代码块
closure1.call()//可以包含多行代码
def closure2 = {println("xxx")println("yyy")
}
//闭包可以使用参数,像定义方法一样
def closure1 = { param -> println(param) }
closure1.call("xxx")//支持多个参数,多个参数不需要像lambda表达式一样放在小括号中
def closure2 = {param1, param2 -> println(param1 + param2)
}
closure2.call(1, 2)
closure2.call("xxx", "yyyy")//参数可以声明具体的类型
def closure3 = {int param1, int param2 -> println(param1 + param2)
}// -> 后有多行代码时,不需要像lambda表达式一样,放在大括号中
def closure4 = { param1, param2 ->println(param1)println(param2)
}
def file = new File("D:/document/1.txt")//闭包可以作为函数参数
file.withWriter({ write -> write.write("xxx") })
file.withWriter("utf-8", { write -> write.write("xxx") })//如果函数体本身的操作就是调用闭包,可以将闭包写成函数体形式
file.withWriter {write -> write.write("xxx")
}
file.withWriter("utf-8") {write -> write.write("xxx")
}

类的定义

class Person {Integer idString namestatic void main(String[] args) {//使用自动提供的map型参数的构造方法def person1 = new Person(["id": 1, "name": "chy"])//可以缺省[]def person2 = new Person("id": 1, "name": "chy")//或者使用java的mapdef map = new HashMap<String, Object>()map.put("id", 1)map.put("name", "chy")def person3 = new Person(map)}}

1、groovy 的访问权限控制符默认是 public,一般也是使用 public。

2、groovy会自动给 public 型成员(包括static成员)添加 getter、setter 方法,实例成员通过实例访问,静态成员通过类名访问。

可以直接通过属性名访问(实质是调用对应的getter、setter方法),也可以通过getter、setter方法访问,或者通过字符串属性名形式的 getProperty()、setProperty() 方法访问。

3、如果没有给 groovy 类显式提供构造器,在 groovy 中会自动提供无参构造器、map型参数的构造器,java 中调用 groovy 类时,则只提供无参构造器

4、在 groovy 类中使用 lombok 的注解会失效,部分注解可以使用 groovy-all 提供的,如下

@Slf4j
@Builder
@ToString
@EqualsAndHashCode

IO

groovy 自动导入了 java.io,可以使用 java 的 io,也可以使用 groovy 的 io,此处介绍 groovy 的 io。

控制台输出

print(user.name)
println(user.name)
printf("user:%s", user)

File类

groovy 的 File 类是在 java File 类的基础上进行增强,提供了更多、更简便的方法

File file = new File("D:/document", "1.txt")
File file1 = new File("D:/document/1.txt")//获取File对象信息
println(file.name)
println(file.getName())
println(file.isDirectory())

文件读

//获取文本文件的全部内容
def text1 = file.text
def text2 = file.getText()
def text3 = file.getText("uft-8")//获取包含全部内容的字节数组,byte[]
def bytes1 = file.bytes
def bytes2 = file.getBytes()
//逐行遍历
file.eachLine {line -> println(line)
}//闭包可以缺省临时变量,直接使用默认的临时变量名 it
file.eachLine {println(it)
}//可以指定字符集
file.eachLine('utf-8') {println(it)
}//可以携带行号
file.eachLine { line, lineNumber ->println("第${lineNumber}行:$line")
}//收集每一行到list中,一行即一个元素
def list = file.collect()//收集每一行到数组中
def arr = file.collect() as String[]
//可以使用 InputStream。手动关闭
def fis1 = file.newInputStream()
//...
fis1.close()//自动关闭
file.withInputStream {fis2 -> //...
}//也可以使用 Reader
def reader1 = file.newReader()
//...
reader1.close()file.withReader {reader -> //...
}//Reader可以指定字符集
def reader2 = file.newReader("utf-8")
//...
reader1.close()file.withReader("utf-8"){reader -> //...
}

文件写

groovy的写操作,如果指定的文件不存在,都会先自动创建再写入

//文本文件可以直接设置内容
file.text="xxx"
file.setText("xxx")
file.setText("xxx","utf-8")//也可以用 bytes、setBytes() 写入byte[]//都是覆盖:先删除全部原内容,再写入
//可以使用 OutputStream
file.withOutputStream {fos2 -> //...
}//也可以使用Writer。覆盖
file.withWriter { write ->write.write("xxx")
}//追加
file.withWriterAppend { write ->write.write("xxx")
}//Writer可以指定字符集
file.withWriter("utf-8") { writer ->writer.write("xxx")
}file.withWriterAppend("utf-8") {write -> //...
}
//都可以手动关闭def fos1 = file.newOutputStream()
//...
fos1.close()def writer1 = file.newWriter()
//是否是append 追加,默认false 直接覆盖
def writer2 = file.newWriter(true)
def writer3 = file.newWriter("utf-8")
def writer4 = file.newWriter("utf-8", true)
//...
writer1.close()
writer2.close()
writer3.close()
writer4.close()def printWriter1 = file.newPrintWriter()
def printWriter2 = file.newPrintWriter("utf-8")
//...
printWriter1.close()
printWriter2.close()
def src = new File("D:/document/1.txt")
def dest = new File("D:/document/2.txt")//追加也可以用运算符 <<
src << '''Into the ancient pondA frog jumpsWater’s sound!'''//把一个文件的内容拷贝到另一个文件中(复制),<< 都是以追加形式写入的
dest << src.text

遍历文件树

def dir = new File("D:/笔记")//遍历直接子文件、子文件夹,只遍历直接的
dir.eachFile() {file -> println(file.absolutePath)
}//递归遍历所有的文件、文件夹
dir.eachFileRecurse() {file -> println(file.absolutePath)
}//可以筛选类型,FILES 文件、DIRECTORIES 目录,默认为 ALL
dir.eachFile(FileType.DIRECTORIES) {file -> println(file.absolutePath)
}dir.eachFileRecurse(FileType.FILES) { file -> println(file.absolutePath)
}
//eachFile包含了文件、文件夹,eachDir则只包含文件夹//遍历直接子文件夹
dir.eachDir {dir1 -> println(dir1.absolutePath)
}//递归遍历所有的文件夹
dir.eachDirRecurse() {dir1 -> println(dir1.absolutePath)
}

说明

1、闭包可以缺省临时变量,直接使用默认的临时变量名 it,it 即 item 的简写。
 
2、groovy的自动资源管理

groovy提供的闭包形式的IO操作,实质是对 try…finally 的封装,即使执行时发生了异常,也会自动关闭资源,无需手动关闭。
 
3、可以使用基于字节的 InputStream、OutputStream,也可以使用基于字符的 Reader、Write,基于字符的IO流都可以指定字符集。

单元测试

继承 GroovyTestCase,方法名以 test 开头,空参,返回值类型 void

import org.junit.Assertclass Test1 extends GroovyTestCase {void testXxx() {def str = "xxx"//groovy的断言assert "xxx1" == str//也可以用junit的断言Assert.assertEquals("xxx", str)}}

可以用 GroovyTestSuite 组装多个要执行的测试类,用 TestRunner 执行批量测试

class AllTest extends GroovyTestCase {void testAll() {//组装要执行的多个测试类def allTest = new GroovyTestSuite()allTest.addTestSuite(Test1.class)allTest.addTestSuite(Test2.class)//执行测试TestRunner.run(allTest)}}

Groovy使用指南相关推荐

  1. 《Groovy官方指南》目录

    入门篇(Getting Started) 下载Groovy(Download Groovy) 安装Groovy (Install Groovy) 与Java的比较 (Differences with ...

  2. Groovy简介和一点资源

    Groovy简介 简单地说,Groovy是一门基于JVM的动态语言.我们可以把它当成JVM上的Python语言来使用.而且Groovy的有些语法都和Python.Ruby等脚本语言很相似.Groovy ...

  3. Gradle用户指南(章9:Groovy快速入门)

    Gradle用户指南(章9:Groovy快速入门) 你可以使用groovy插件来构建groovy项目.这个插件继承了java插件的功能,且扩展了groovy编译.你的项目可以包含groovy代码.ja ...

  4. Gradle核心思想(三)Groovy快速入门指南

    本文首发于微信公众号「刘望舒」 关联文章 Gradle核心思想(一)为什么现在要用Gradle? Gradle核心思想(二)Gradle入门前奏 Gradle核心思想(三)Groovy快速入门指南 G ...

  5. 基于Groovy的Spock单元测试框架入门指南

    文章目录 1. Spock Primer 基本概念 1.1 对比Junit 1.2 Imports 1.3 Specification测试类 1.4 Fields 属性 1.5 Fixture Met ...

  6. Android Gradle(三)Groovy快速入门指南

    本文首发于微信公众号「刘望舒」 原文链接:Groovy快速入门看这篇就够了 前言 在前面我们学习了为什么现在要用Gradle?和Gradle入门前奏两篇文章,对Gradle也有了大概的了解,这篇文章我 ...

  7. android groovy方法,Android Gradle从入门到精通(三)Groovy快速入门指南

    前言 在前面我们学习了为什么现在要用Gradle?和Gradle入门前奏两篇文章,对Gradle也有了大概的了解,这篇文章我们接着来学习Groovy的基础,要想学好Gradle,Groovy是必须要掌 ...

  8. Groovy快速入门指南

    1.Groovy概述 Groovy是Apache 旗下的一种基于JVM的面向对象编程语言,既可以用于面向对象编程,也可以用作纯粹的脚本语言.在语言的设计上它吸纳了Python.Ruby 和 Small ...

  9. Elasticsearch 参考指南(脚本)

    脚本 脚本模块使你可以使用脚本来评估自定义表达式,例如,你可以使用脚本将"脚本字段"作为搜索请求的一部分返回,或者为查询评估自定义分数. 默认脚本语言是Painless,附加的la ...

  10. Java基础20:Java8新特性终极指南

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

最新文章

  1. pyspark汇总小结
  2. Linux—shell中$(( ))、$( )、``与${ }的区别
  3. 怎么复制黑苹果config配置_估计是最后一次折腾黑苹果,技嘉 Z490 Vision D 的 OC 配置分享...
  4. centos6,7grub防止其他用户通过单用户系统破解root密码
  5. 二项式反演[bzoj3622]已经没有什么好害怕的了
  6. FSAF 让网络自己决定实例输出层
  7. PHP企业级开发环境配置全攻略-IDE+SVN++(转)
  8. 互联网日报 | 北斗三号全球卫星导航系统正式开通;拼多多上线首届“真香节”;海尔电器私有化草案出炉...
  9. sqlserver数据库原理
  10. Julia : varinfo() 与工作空间,@isdefined, @which
  11. 【微信商城小程序怎么弄】微信商城小程序开发的基本流程
  12. IMF 自定义 IMFTimer、IMFTimerTask
  13. 题目连接:http://acm.zznu.edu.cn/problem.php?id=1329
  14. 小程序内识别二维码调查
  15. Python nose测试大法
  16. 关于行业、以太坊与个人,V神的29条感悟 |链捕手
  17. 读书笔记:《机器人SLAM导航核心技术与实战》导读
  18. MIPCMS高仿博客一号博客/新闻/资讯自适应模版
  19. FreeRapid v0.9u3
  20. 【Swift 60秒】80 - Classes: Summary

热门文章

  1. android LBS模式,android: 如何开启webview的LBS功能
  2. itext设置字体间距_设计时sketch中字体行高到底该如何设置
  3. 利用Thumbnilator对图片加文字水印
  4. cmos电路多余输入端能否悬空_【技术分享】CMOS集成电路中多余输入端为何不能悬空?...
  5. 计算机用户名和初始密码,电脑默认的用户名和密码是多少
  6. 最近复习了一下JavaScript
  7. ADS1115的IIC通信
  8. Spring的事务传播特性
  9. 佛罗里达大学计算机博士,2020年佛罗里达大学博士含金量
  10. 【解决】计算机用户名是中文名导致软件安装失败!