2--Gradle入门 - Groovy简介、基本语法
Gradle 需要 Groovy 语言的支持,所以本章节主要来介绍 Groovy 的基本语法。
1.Groovy 简介
在某种程度上,Groovy 可以被视为Java 的一种脚本化改良版,Groovy 也是运行在 JVM 上,它可以很好地与 Java 代码及其相关库进行交互操作。它是一种成熟的面向对象编程语言,既可以面向对象编程,又可以用作纯粹的脚本语言。大多数有效的 Java 代码也可以转换为有效的 Groovy 代码,Groovy 和 Java 语言的主要区别是:完成同样的任务所需的Groovy 代码比 Java 代码更少。其特点为:
-
功能强大,例如提供了动态类型转换、闭包和元编程(metaprogramming)支持
-
支持函数式编程,不需要main 函数
-
默认导入常用的包
-
类不支持 default 作用域,且默认作用域为public。
-
Groovy 中基本类型也是对象,可以直接调用对象的方法。
-
支持DSL(Domain Specific Languages 领域特定语言)和其它简洁的语法,让代码变得易于阅读和维护。
-
Groovy 是基于Java 语言的,所以完全兼容Java 语法,所以对于java 程序员学习成本较低。详细了解请参考:http://www.groovy-lang.org/documentation.html
2. Groovy 安装 SDK
下载Groovy SDK
官网下载地址:https://groovy.apache.org/download.html
下载后为一个 zip 包,如下:
解压缩 SDK
将 SDK 解压之后,下面就可以配置环境变量了。
配置环境变量
变量名:GROOVY_HOME
变量值:解压后的目录
添加path路径中:%GROOVY_HOME%\bin
测试查询 Groovy 版本
C:\Users\Administrator>groovy -v
Groovy Version: 4.0.3 JVM: 1.8.0_91 Vendor: Oracle Corporation OS: Windows 10
执行如下:
查询版本之后,可以配置完成了。
3. Idea 创建 Groovy 项目
Idea创建项目的时候选择Groovy
File - New - Project / Module(本文以建立Project为例) - 选择Groovy - 点击Creater(选择下载的Groovy SDK包) - 下一步命名Project - 点击OK。
此时即建立了Groovy项目。
配置项目工程的 out 输出目录
在 Project 工程配置 out 输出目录。
在模块的路径设置继承 Project 的 out 路径
编写 Demo 输出 HelloWorld
创建 Groovy 类
编写 Demo
package test
/**
* @author Aron.li* @date 2022/7/6 8:57
*/
class demo {
static void main(String[] args) {
println("Hello,World!Groovy!");
}
}
执行代码如下:
查看生成的 demo 执行类
可以看到实现了 GroovyObject
类
编写 Demo 脚本
groovy 也可以使用脚本的方式来实现,不用写成类:
package test
def str1 = 'hello world'
printf("message: ${str1}")
查看生成的输出类:
可以看到,如果是脚本的写法,那么生成类则是继承 Script
类。
4. Groovy 基本语法
创建一个以 .groovy 为后缀的文件,我们可以在这文件中像开发java代码一样简单的去使用 groovy,并且 groovy 提供的语法更加简洁。
我们可以完全像开发 Java 代码一样去编写 Groovy,也可以根据 Groovy 的语法来简化编写。
第一个 Hello world 程序
class Example {
static void main(String[] args) {
// 使用 println 就可打印输出,并且类和方法默认就是public,可以不用写
println('Hello World');
}
}
运行
Hello World
Groovy 的导入语句
和 Java 一样,都是使用 Import 进行导入
import groovy.xml.MarkupBuilder // Import 进行导入需要的类
def xml = new MarkupBuilder() // def 就是动态类型,在Groovy可以不用指定具体的类型,就像js中的var一样
在编译的 Groovy 字节码文件中,Groovy 已经默认帮我们导入了一些jar包,这些 jar 包可以不用再显示的导入
import java.lang.*
import java.util.*
import java.io.*
import java.net.*
import groovy.lang.*
import groovy.util.*
import java.math.BigInteger
import java.math.BigDecimal
Groovy 的注释
和 Java 一样,支持单行 //
和多行注释 /**/
// Using a simple println statement to print output to the console
/* This program is the first program
This program shows how to display hello world */
Groovy 的分号
;
分号,可以用来区分不同的代码块。
在 Groovy 编写中可以,可以省略分号符
Groovy 的标识符
和 Java 一样,标识符就是变量名,声明规则和 Java 一样,可以以字母开头,美元或下划线。但不能以数字开头。
Groovy 的关键字
大部分关键字和 Java 中的用法一样
as | assert | break | case |
---|---|---|---|
catch | class | const | continue |
def | default | do | else |
enum | extends | FALSE | Finally |
for | goto | if | implements |
import | in | instanceof | interface |
new | pull | package | return |
super | switch | this | throw |
throws | trait | TRUE | try |
while |
数据类型
Groovy 的内置数据类型和 Java 一样有8种。byte、short、int、long、float、double、char、boolean
字符串:String
并且都有其对应的封装类
变量
变量也和 Java 一样,除了使用基本数据类型和引用类型,还可以使用def
动态数据类型来声明变量。
// 和java的区别就是多了,def动态类型
def a = 1; // 在编译时会自动转化为int
def a = 'aa';
运算符
大部分运算符和 Java 一样,如:算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符
范围运算符
与 Java 不同点在于,新增了 范围运算符
def range = 0..5
范围运算符通过..
来指定其开始和结束的范围。
上面示例就简单的定义了一个,从0到5的范围。
/**
* @author Aron.li* @date 2022/7/11 7:59
*/
class RangeDemo {
public static void main(String[] args) {
// 定义 5~10 的范围
def range = 5..10
// 打印范围
println(range)
// 取范围中的数据
println(range.get(2))
// 遍历范围数据
range.forEach( e -> {
print(e + ', ')
})
}
}
运行
运算符优先级
运算符 | 名称 |
---|---|
++ ,-- ,+ ,- | 预增/减(自增/减),一元加,一元减 |
*, /, % | 乘法,除法,取模 |
+,- | 加法,减法(二元) |
==,!=, <=> | 等于,不等于,比较运算符 |
& | 二进制/位运算符与 |
^ | 二进制/位异或 |
` | ` |
! | 逻辑非 |
&& | 逻辑与 |
` | |
=,+=,-=,*=,/=,%=,**= | 各种赋值运算符 |
循环
Groovy 中的循环和 Java 中一样,包含循环跳出和结束循环等
while、for、break、continue
while 语句
package test.basicUsage
/**
* 循环Demo
* while、for、break、continue
*
* @author Aron.li* @date 2022/7/11 8:17
*/
class CycleDemo {
public static void main(String[] args) {
// while demo
println("while demo .................")
int i = 0
while (i < 5){
if ( i == 4) break
if ( i == 2) continue
println("i = " + i)
i ++
}
}
}
运行如下:
for in 语句
在 Java 中我们常常使用foreach
来遍历
for(String str : strList){
...
}
而在 Groovy 中提供了for in
语句,其使用方法和 Java 一样,只是关键字不同
for(def str in strList){
println(str);
}
示例代码如下:
// for in
println("for in .................")
def strList = ['hello', 'world']
for (def str in strList){
println(str)
}
运行结果如下:
for in .................
hello
world
for 语句
// for
println("for .................")
for (int j = 0; j < 5; j++) {
println("j = " + j)
}
运行结果如下:
for .................
j = 0
j = 1
j = 2
j = 3
j = 4
continue
// continue
println("continue .................")
for (int j = 0; j < 5; j++) {
if (j == 3) continue
println("j = " + j)
}
运行结果如下:
continue .................
j = 0
j = 1
j = 2
j = 4
break
// break
println("break .................")
for (int j = 0; j < 5; j++) {
if (j == 3) break
println("j = " + j)
}
运行结果如下:
break .................
j = 0
j = 1
j = 2
条件语句
Groovy 中的条件语句和 Java 中的一样,其关键字如下
if、else、switch
等
包括其嵌套使用等
if 语句
package test.basicUsage
/**
* 条件语句
*/
class ConditionDemo {
public static void main(String[] args) {
// if 条件语句
println("if 条件语句............")
int a = 20
if (a < 10){
println("a < 10, a = " + a)
} else if (a > 20){
println("a > 20, a = " + a)
} else {
println("else, a = " + a)
}
}
}
运行结果如下:
if 条件语句............
else, a = 20
Switch语句
// Switch语句
println("Switch语句 ............")
int b = 2
switch (b){
case 1:
println("The value of a is One")
break
case 2:
println("The value of a is Two")
break
case 3:
println("The value of a is Three")
break
case 4:
println("The value of a is Four")
break
default:
println("The value is unknown")
break
}
运行结果如下:
Switch语句 ............
The value of a is Two
嵌套Switch语句
// 嵌套 Switch 语句
int i = 0
int j = 1
switch(i) {
case 0:
switch(j) {
case 0:
println("i is 0, j is 0")
break
case 1:
println("i is 0, j is 1")
break
default:
println("nested default case!!")
}
break
default:
println("No matching case found!!")
}
运行结果如下:
i is 0, j is 1
案例
1.案例1:基本语法
groovy 中使用 def 定义变量、方法,不建议使用具体的类型:
package test.basicUsage
/**
* def 定义各种变量
* - groovy 中使用 def 定义变量、方法,不建议使用具体的类型
*
* @author Aron.li* @date 2022/7/16 15:38
*/
class defDemo {
static def msg (str){
// 如果没有return,则会以最后一行返回消息
"msg: ${str}"
}
static def add(num1, num2){
return num1 + num2
}
static void main(String[] args) {
// 输出msg方法的返回值
println(msg("hello world"))
// Example of an Integer using def
def a = 100
println(a)
// Example of an float using def
def b = 100.10
println(b)
// Example of an Double using def
def c = 100.101
println(c)
// Example of an String using def
def d = "HelloWorld"
println(d)
// Example of an Func return using def
def sum = add(100, 10)
println(sum)
}
}
注意事项案例
为了更加方便理解,下面我定义一个类,然后再写一个 script 脚本来调用该类的属性、方法:
-
Demo1BasicNotice
package test.demo
class Demo1BasicNotice {
/**--------------------------------------------------
* 1.groovy中使用def 定义属性、方法,def支持动态类型声明
* 2.单行注释:// 多行注释: /**
* 3.gradle语句最后的;(分号)是可以省略的
* 4.groovy可以为属性自动生成getter、setter方法
* 5.方法声明时:参数类型、返回值类型、return关键字可以省略,方法调用时,再不引起歧义的地方,可以省略()
* 6.变量应用时:在不引起歧义的前提下{}也可以省略,再容器引起歧义的地方就不能省略{}
* 7.对象属性赋值时:
* 方式1: 对象.属性名=
* 方式2: 对象["属性名"]=
* 方式3: 对象.属性setter方法()
* 方式4: 具名构造器的方式
* 读取属性值:
* 方式1: 对象.属性名
* 方式2: 对象["属性名"]
* 方式3: 对象.属性getter方法
*
* --------------------------------------------------
*/
// 定义属性
def name = "李小龙"
def age = 10
def desc = "描述信息"
def address = "地址信息"
// 定义方法
def sendMessage(msg){
"msg: $msg"
}
def sum(num1, num2){
"sum = ${num1 + num2}"
}
}
-
Demo1BasicNoticeScript.groovy
package test.demo
// 获取对象
def notice = new Demo1BasicNotice()
// 设置属性、读取属性
notice.age = 30
println("notice.age = $notice.age")
notice["desc"] = "demo 描述信息"
println("desc = ${notice["desc"]}")
notice.setAddress("深圳市南山区")
println("address = ${notice.getAddress()}")
// 使用方法
def message = notice.sendMessage("发送消息...")
println(message)
def sum = notice.sum(10, 15)
println(sum)
执行如下:
2. 案例 2:引号说明
package test.demo
//---------------------------- 字符串 ------------------------------
def desc="测试"
def str1='单引号, 不支持变量引用 ${desc},不支持换行操作 '
println(str1)
def str2 = "双引号,支持变量应用 ${desc}, 不支持换行操作"
println(str2)
def str3 = """
模板字符串: ${desc}, 支持换行操作\n
换行测试.....
"""
println(str3)
// 基本数据类型也可以作为对象使用,可以调用对象的方法
println(str1.getClass().toString())
println(str2.getClass().toString())
println(str3.getClass().toString())
执行如下:
3.案例 3:三个语句结构
Groovy 支持顺序结构从上向下依次解析、分支结构(if..else、if..else if ..else..、switch..case、for、while、do..while)
具体参考官网:http://www.groovy-lang.org/semantics.html#_conditional_structures
4. 案例 3:类型及权限修饰符
Groovy 中的类型有:
-
原生数据类型及包装类
-
类、内部类、抽象类、接口
-
注解
-
Trait: 可以看成是带有方法实现的接口
权限修饰符: public、protected、private
拓展:Groovy 类与 Java 类之间的主要区别是:
-
没有可见性修饰符的类或方法自动是公共的(可以使用一个特殊的注释来实现包的私有可见性)。
-
没有可见性修饰符的字段将自动转换为属性,不需要显式的 getter 和 setter 方法。
-
如果属性声明为 final,则不会生成 setter。
-
一个源文件可能包含一个或多个类(但是如果一个文件不包含类定义的代码,则将其视为脚本)。脚本只是具有一些特殊约定的类,它们的名称与源文件相同(所以不要在脚本中包含与脚本源文件名相同的类定义)。
提 示 : 有 关 Groovy 中 各 种 各 样 的 数 据 类 型 和 权 限 修 饰 符 及 Goovy 与 Java 区 别 请 参 考 :
http://www.groovy-lang.org/objectorientation.html#_modifiers_on_a_property
5. 案例 5:集合操作
Groovy 支持List、Map 集合操作,并且拓展了 Java 中的API,具体参考如下方法:
List
:
-
add()
:添加某个元素plus():添加某个list 集合 -
remove():
删除指定下标的元素removeElement():删除某个指定的元素removeAll(): 移除某个集合中的元素 -
pop()
:弹出list 集合中最后一个元素putAt():修改指定下标的元素 -
each()
:遍历 -
size()
: 获取list 列表中元素的个数 -
contains()
: 判断列表中是否包含指定的值,则返回 true
Map
:
-
put()
:向map 中添加元素 -
remove()
:根据某个键做移除,或者移除某个键值对 -
+、-
:支持 map 集合的加减操作 -
each()
:遍历map 集合
请参考官网:http://www.groovy-lang.org/syntax.html#_number_type_suffixes
提示:可以把不同的基本类型添加到同一集合中。
List 增删查改:
package test.demo
//---------------------------list增删查改操作--------------------
//----------------------1.增----------------------
//1.1. 增:在集合中添加元素
println("1.1. 增:在集合中添加元素")
def list = [5, 6, 7, 8]
println(list)
assert list instanceof List
list.add(12)
println(list)
println(list.size())
//1.2. 增:集合与集合相加
println("1.2. 增:集合与集合相加")
def list2 = [1, 2, 3, 4]
def list3 = list.plus(list2)
println(list) // 原来的list集合不改变
println(list3) // 集合相加会生成新的集合
//----------------------2.删-------------------------
//2.1. 删:删除下表为2的元素
println("2.1. 删:删除下表为2的元素")
println("删除之前的list: ${list}")
list.remove(2)
println("删除之后的list: ${list}")
//2.2 删:删除集合中指定的元素
println("2.2 删:删除集合中指定的元素")
println("删除之前的list: ${list}")
list.removeElement(12)
println("删除之后的list: ${list}")
//2.3 删:从list集合中移除list3集合中的元素
println("2.3 删:从list集合中移除list3集合中的元素")
def list4 = [6, 8]
list.removeAll(list4)
println(list)
//---------------------------3.改-----------------------
println("3.list的修改")
list.putAt(2, 10) // 等效于 list[2]=10
println(list)
//---------------------------4.查------------------------
//4.1 遍历list
println("4.1 遍历list")
[1, 2, 3].each { println("Item: {$it}") }
//4.2 获取list的大小
println("4.2 获取list的大小: ${list.size()}")
//4.3 判断list是否包含指定的值
println("4.3 判断list是否包含指定的值: ${[1, 2, 3].contains(2)}")
Map增删查改
//---------------------------map增删查改操作--------------------
// Key 可以不适用引号,可以使用单引号 '',也可以使用双引号 ""
def map = [J: "Java", "K": "Kotlin", 'G': "Groovy"]
//----------------------1.增----------------------
println("----------------------1.增----------------------")
map.put("P", "Python")
println("map: ${map}")
def map2 = [C: "C++"]
map.putAll(map2)
println("map: ${map}")
//----------------------2.删----------------------
println("----------------------2.删----------------------")
map.remove("P") // 根据某个Key做移除
map.remove("J", "Java") // 移除某个键值对
println("map: ${map}")
//----------------------3.改----------------------
println("----------------------3.改----------------------")
// "-" "+" 操作符
map3 = map - ["K": "Kotlin"]
println("map3: ${map3}")
map4 = map + [G: "Gradle"] // key相同则会覆盖
println("map4: ${map4}")
//----------------------4.查----------------------
println("----------------------4.查----------------------")
map.each { key, value ->
{
println("key: $key, value: $value")
}
}
6.案例 6:类导入
Groovy 遵循 Java 允许 import 语句解析类引用的概念。
import groovy.xml.MarkupBuilder
def xml = new MarkupBuilder()
assert xml != null
Groovy 语言默认提供的导入
import java.lang.*
import java.util.*
import java.io.*
import java.net.*
import groovy.lang.*
import groovy.util.*
import java.math.BigInteger
import java.math.BigDecimal
这样做是因为这些包中的类最常用。通过导入这些样板代码减少了。
参考官网地址:
http://www.groovy-lang.org/structure.html#_imports
7. 案例 7:异常处理
Groovy 中的异常处理和 java 中的异常处理是一样的。
def z
try {
def i = 7, j = 0
try {
def k = i / j
assert false
} finally {
z = 'reached here'
}
} catch ( e ) {
assert e in ArithmeticException
assert z == 'reached here'
}
参考官网地址:
http://www.groovy-lang.org/semantics.html#_try_catch_finally
8. 案例 8:闭包
闭包:Groovy 中的闭包是一个开放的、匿名的代码块,它可以接受参数、也可以有返回值。闭包可以引用其周围作用域中声明的变量。
语法:{ [closureParameters -> ] statements }
其中[ closureParameters-> ]
是一个可选的逗号分隔的参数列表,参数后面是 Groovy 语句。参数类似于方法参数列表, 这些参数可以是类型化的,也可以是非类型化的。当指定参数列表时,需要使用->
字符,用于将参数与闭包体分离。
参考:http://www.groovy-lang.org/closures.html
//闭包体完成变量自增操作
{ item++ }
//闭包使用 空参数列表 明确规定这是无参的
{ -> item++ }
//闭包中有一个默认的参数[it],写不写无所谓
{ println it }
{ it -> println it }
//如果不想使用默认的闭包参数it,那需要显示自定义参数的名称
{ name -> println name }
//闭包也可以接受多个参数
{ String x, int y ->
println "hey ${x} the value is ${y}"
}
//闭包参数也可是一个对象
{ reader ->
def line = reader.readLine()
line.trim()
}
闭包调用方式:闭包是 groovy.lang.Closure
的实例。它可以像任何其他变量一样分配给一个变量或字段。
闭包对象(参数)
闭包对象.call(参数)
def isOdd = { int i -> i%2 != 0 }
assert isOdd(3) == true
assert isOdd.call(2) == false
def isEven = { it%2 == 0 }
assert isEven(3) == false
assert isEven.call(2) == true
特殊说明:可以把闭包当作一个对象,作为参数传递给方法使用
package test.demo
/**=================================================
* 闭包:
* 定义:是一个开放的、匿名的代码块,它可以接受参数、也可以有返回值。闭包可以引用其周围作用域中声明的变量。
* 语法:{ [closureParameters -> ] statements }
* 调用:
* 第一步:将闭包赋值给一个变量
* 第二步:变量名()、变量名.call()
*
* 闭包在实际开发中的使用:作为方法的参数使用
=================================================*/
// 1. 有参数的闭包
println("1. 有参数的闭包")
// 定义闭包
def running = { who ->
println("$who running start .....")
println("$who running end .....")
}
// 调用闭包
running()
running.call("小明")
// 2. 将闭包作为对象参数,传递给闭包
println("2. 将闭包作为对象参数,传递给闭包")
// 2.1 定义无参闭包
println("2.1 无参闭包")
def run(Closure closure) {
println("run start....")
// 执行无参闭包
closure()
println("run end....")
}
// 执行闭包
run {
println("running....")
}
// 2.2 定义有参闭包
println("2.2 有参闭包")
def caculate(Closure closure) {
def num1 = 1
def num2 = 3
println("caculate start....")
// 执行有参闭包
closure(num1, num2)
println("caculate end....")
}
// 执行有参闭包
caculate { x, y -> println("计算结果为: $x + $y = ${x + y}") }
执行如下: