2--Gradle入门 - Groovy简介、基本语法

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

2d2b8eb0d84c11c2a2f0074ed96ec857.png
1685493613971

2. Groovy 安装 SDK

下载Groovy SDK

官网下载地址:https://groovy.apache.org/download.html

dcd07f7115b9372f5fc2d7a21711c724.png

下载后为一个 zip 包,如下:

63c016f994bc0edae8410fd999b52325.png

解压缩 SDK

a4622f57f7c7aa7f69b7b7ac32eacb0a.png

将 SDK 解压之后,下面就可以配置环境变量了。

配置环境变量

变量名:GROOVY_HOME
变量值:解压后的目录
添加path路径中:%GROOVY_HOME%\bin

dcacfbb5f9fa73f89ae6b763e28f8643.png

88dfa7ba6f8eac7192a9759f195492f7.png

测试查询 Groovy 版本

C:\Users\Administrator>groovy -v
Groovy Version: 4.0.3 JVM: 1.8.0_91 Vendor: Oracle Corporation OS: Windows 10

执行如下:

3a1b2e8ffc53453feb3999ea85e374fd.png

查询版本之后,可以配置完成了。

3. Idea 创建 Groovy 项目

Idea创建项目的时候选择Groovy

File - New - Project / Module(本文以建立Project为例) - 选择Groovy - 点击Creater(选择下载的Groovy SDK包) - 下一步命名Project - 点击OK。

此时即建立了Groovy项目。

bdfb3600d262b6f472b65f43a011dfb3.png

484cfa684e2d4cc58cd7570fa63c6a39.png

b06c4379ecb12e29c3b92a06f8b49583.png

f97f53940e748542495391d2717dade1.png

配置项目工程的 out 输出目录

在 Project 工程配置 out 输出目录。

5c2fc835d3f5740ab673bd64fe0dca82.png

在模块的路径设置继承 Project 的 out 路径

d104377d6ee88fa84534b06ed4397370.png

编写 Demo 输出 HelloWorld

创建 Groovy 类

21f3ef74a1b6d3e99e24eb84ee45d983.png

编写 Demo

package test

/**
 * @author Aron.li* @date 2022/7/6 8:57
 */
class demo {
    static void main(String[] args) {
        println("Hello,World!Groovy!");
    }
}

执行代码如下:

747a000f21289a39e270ef565a5fe723.png

查看生成的 demo 执行类

90a56d0b3baf3d80f42c1bcd32618216.png

可以看到实现了 GroovyObject

编写 Demo 脚本

groovy 也可以使用脚本的方式来实现,不用写成类:

9e5824f3257a8f6d9226f690eb0aa6a0.png

1685578418631
package test

def str1 = 'hello world'

printf("message: ${str1}")

查看生成的输出类:

bdb64be97518ed4b9bfdd649361bf754.png

1685578548648

可以看到,如果是脚本的写法,那么生成类则是继承 Script 类。

4. Groovy 基本语法

创建一个以 .groovy 为后缀的文件,我们可以在这文件中像开发java代码一样简单的去使用 groovy,并且 groovy 提供的语法更加简洁。

我们可以完全像开发 Java 代码一样去编写 Groovy,也可以根据 Groovy 的语法来简化编写。

第一个 Hello world 程序

class Example {
   static void main(String[] args) {
      // 使用 println 就可打印输出,并且类和方法默认就是public,可以不用写
      println('Hello World');
   }
}

运行

9be5645aaf4c200b833861a3507458c0.png

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 中的用法一样

asassertbreakcase
catchclassconstcontinue
defdefaultdoelse
enumextendsFALSEFinally
forgotoifimplements
importininstanceofinterface
newpullpackagereturn
superswitchthisthrow
throwstraitTRUEtry
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 + ', ')
        })
    }

}

运行

e863de80f23ad3a97b2a895881ddf14d.png

可以发现,范围变量,本质就是封装了一层数组。在操作时,通过其下标进行存取。

运算符优先级

运算符名称
++ ,-- ,+ ,-预增/减(自增/减),一元加,一元减
*, /, %乘法,除法,取模
+,-加法,减法(二元)
==,!=, <=>等于,不等于,比较运算符
二进制/位运算符与
^二进制/位异或
``
逻辑非
&&逻辑与
`
=,+=,-=,*=,/=,%=,**=各种赋值运算符

循环

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 ++
        }
    }
}

运行如下:

86b3befe7a4fb9391e27b568e66141e8.png

image-20220711082239363

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 定义变量、方法,不建议使用具体的类型:

9fd877c69c44110009e9f8e2fcbfbcc2.png

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)

执行如下:

7b3e8ab07e1cce278f7e2ceaa017637d.png

1685669998610

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())

执行如下:

04ae3e1efdcda3e1b43ad819fb5f5e9e.png

1685766297899

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 中的类型有:

  1. 原生数据类型及包装类

6a14382a2095d1e7ded2003a1bc12134.jpeg

img
  1. 类、内部类、抽象类、接口

  2. 注解

  3. Trait: 可以看成是带有方法实现的接口

权限修饰符: public、protected、private

拓展:Groovy 类与 Java 类之间的主要区别是:

  1. 没有可见性修饰符的类或方法自动是公共的(可以使用一个特殊的注释来实现包的私有可见性)。

  2. 没有可见性修饰符的字段将自动转换为属性,不需要显式的 getter 和 setter 方法。

  3. 如果属性声明为 final,则不会生成 setter。

  4. 一个源文件可能包含一个或多个类(但是如果一个文件不包含类定义的代码,则将其视为脚本)。脚本只是具有一些特殊约定的类,它们的名称与源文件相同(所以不要在脚本中包含与脚本源文件名相同的类定义)。

提 示 : 有 关 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}") }

执行如下:

246485f844e116262d2a2ebd8e145352.png

1685770311565
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

海洋的渔夫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值