⭐表示重要。

第一章:Groovy 简介

1.1 概述

  • 到目前为止,所能够接触到的 Gradle 从整体运行来看,都非常类似于 Maven 。需要注意的是,Gradle 的功能一定要比Maven 多(毕竟是后起之秀)。但是,最为核心的问题在于:Gradle 是基于 build.gradle 配置文件进行管理的,在 build.gradle 中有如下的一些程序语法:
  1. tasks.withType(JavaCompile) { // 针对程序编译的任务进行配置
  2. options.encoding = "UTF-8"
  3. }
  1. test { // 进行测试任务的配置
  2. useJUnitPlatform() // 使用 Junit 平台
  3. }
  • 实际上,现在所能够见到的这些语法都属于 Apache 推出的 Groovy 脚本语法形式,如果想更加灵活的去使用 Gradle 构建工具,那么最为核心的关键就在于 掌握 Groovy 编程语法

1.2 Groovy 简介

  • Groovy 是一种基于 JVM (Java 虚拟机)的敏捷开发语言,它结合了 Python、Ruby 和 Smalltalk 的许多强大特性,Groovy 代码能够和 Java 代码很好的结合,也能用于扩展现有代码。由于其运行在 JVM 上的特性,Groovy 也可以使用其它非 Java 语言编写的库。

1.jpg

总结:Groovy = Java 核心类库 + Python 语法形式 + Ruby 特点。

2.png

  • 如果要想进行 Groovy 脚本的编写,那么就需要在当前的电脑中进行 Groovy 工具的安装。

注意:Gradle 内部自带有 Groovy 处理解析工具,所以如果基于 Gradle 使用,就不需要再单独安装 Groovy 了。

1.3 Groovy 的特点

  • ① Groovy 是一个基于 Java 虚拟机的敏捷动态语言。
  • ② Groovy 构建在强大的 Java 语言之上,并吸收了 Python、Ruby 和 SmallTalk 等语言中许多特性。
  • ③ 为 Java 开发者提供了现代最流行的编程语言特性,而且学习成本很低。
  • ④ 支持 DSL(Domain Specific Language,领域定义语言)和其它简洁的语言,让你的代码变得易于阅读和维护。
  • ⑤ Groovy 拥有处理原生类型、面向对象以及一个 Ant DSL,使得创建 Shell Scripts 变得非常简单。
  • ⑥ 在开发 WEB、GUI、数据库或控制台程序的时候通过减少框架性代码大大提高了开发者的效率。
  • ⑦ 支持单元测试和模拟(对象),可以简化测试。
  • ⑧ 无缝集成所有已经存在的 Java 对象和类库。
  • ⑨ 支持编译成 Java 字节码,这样可以在任何使用 Java 的地方使用 Groovy。
  • ……

1.4 Groovy 的安装(⭐)

3.png

  • 下载得到的 Groovy 工具是一个压缩包,直接对其进行解压缩、进行 GROOVY_HOME 配置以及环境变量的配置。
  1. GROOVY_HOME=D:\develop\groovy-3.0.9

4.gif

5.png

6.png

7.png

8.png

9.png

  1. Path=%GROOVY_HOME%\bin

10.png

11.png

12.png

13.png

  • 测试 Groovy 是否安装成功:
  1. groovy -v

14.png

15.png

1.5 交互式编程

  • Groovy 直接提供有交互式编程,输入 groovysh 命令即可。
  1. groovysh

16.png

  • 在 Python 语言中可以使用 print 内容println 内容 的形式进行内容信息的输出,那么在 Groovy 也可以采用类似的形式进行信息的输出。
  1. print “你好,Groovy

17.png

  • 在使用 Groovy 编程的时候,由于吸收了 Python 语法的特点,所以在 Groovy 中也可以使用单引号代替 双引号:
  1. print '你好,Groovy'

18.png

  • 如果此时不希望每次都使用 print 语法进行输出,也可以直接编写字符串:
  1. '你好,Groovy'

19.png

  • 在实际 Java 开发中,可以使用 + 实现字符串的拼接操作,那么,在 Groovy 中也提供了这样的功能:
  1. '你好' + 'Groovy'

20.png

  • 在 Groovy 中提供了一个内置编辑器的开发环境,直接使用 groovyconsole 命令即可启动(如果退出 GroovyShell 形式的交换环境,才能使用 groovyconsole 命令):
  1. groovyconsole

21.gif

1.6 基于 IDEA 开发 Groovy 项目

  • 如果开发者使用的是 IDEA 开发工具,那么也可以基于 IDEA 开发工具创建 Groovy 项目,并且只需要配置好要使用的 Goovy-SDK 的路径即可。

22.png

23.png

24.png

  • 在 IDEA 工具中直接创建 Groovy 脚本程序即可。

25.png

26.png

  • 代码内容如下:
  1. package com.github.fairy.era
  2. /**
  3. * @author 许大仙
  4. * @version 1.0
  5. * @since 2021-12-21 09:38
  6. */
  7. println '你好啊,Groovy' // 使用了类似 Python 2.x 的语法结构
  8. println('你好啊,Java') // 使用了类似 Python 3.x 的语法结构

注意:目前 Groovy 以 JDK 1.8 为主,如果以后有更新,也会以 JDK-LTS 为主。

第二章:Groovy 基本语法

2.1 概述

  • 虽然 Groovy 吸收了很多编程语言的特点(Java 类库 + Python 语法),但是其本身也有一些自己语法的要求,下面针对一些基础性的语法进行说明。

2.2 注释

  • 所有的程序开发一定存在有注释,既然 Groovy 使用的是 Java 的核心结构,那么也支持三种注释。
  • ① 单行注释:
  1. package com.github.fairy.era
  2. // 这是单行注释
  3. println '你好啊,Groovy'
  4. println('你好啊,Java')
  • 多行注释:
  1. package com.github.fairy.era
  2. /* 这是多行注释 */
  3. println '你好啊,Groovy'
  4. println('你好啊,Java')
  • 文档注释:
  1. package com.github.fairy.era
  2. /**
  3. * 这是文档注释
  4. *
  5. * @author 许大仙
  6. */
  7. println '你好啊,Groovy'
  8. println('你好啊,Java')

2.3 标识符

  • Java 中的标识符:
    • ① Java 中的标识符只能使用 26 个英文字母大小写,0~9 的数字,下划线 _ 和美元符号 $
    • ② 不能使用 Java 的关键字或保留字和特殊值。
    • ③ 数字不能开头。
    • ④ 不能包含空格。
    • ⑤ 严格区分大小写。
  • Groovy 中的标识符同样遵循 Java 中的标识符规则,但是在 Groovy 中,如果要进行变量的定义可以使用 def 关键字来完成。

  • 示例:

  1. package com.github.fairy.era
  2. def message = "Groovy" // 定义一个字符串变量
  3. println 'message变量的内容是:' + message // 输出 message 变量的内容
  4. println message.getClass() // 输出 message 变量对应的 Class 类型
  5. println message.class // 输出 message 变量对应的 Class 类型
  6. println '字符串转大写:' + message.toUpperCase()
  7. println '字符串转小写:' + message.toLowerCase()

总结:在整个的 Groovy 代码编程过程之中,所有的程序调用都和 Java 非常类似,如果你的 Java 基础还可以的话,一般都可以使用编写 Groovy 程序。

2.4 def 关键字

  • 在 JDK 10 之后,Java 提供了 var 关键字,这个关键字最大的特点就在于:根据根据赋值的类型来推断其变量对应的类型(Lombok 中也有这样的特性),但是有一个最大的问题:变量类型一旦固定就不可改变。
  • 在 Groovy 中,使用 def 关键字定义的所有变量的类型都是可以动态进行改变的。

  • 示例:

  1. package com.github.fairy.era
  2. def num = 10
  3. println num.getClass() // class java.lang.Integer
  4. num = '你好啊,Groovy'
  5. println num.getClass() // class java.lang.String
  6. num = 3.14
  7. println num.getClass() // class java.math.BigDecimal
  8. num = 'hello'
  9. println num.getClass() // class java.lang.String

2.5 数据类型

  • 在 Java 中,所有的数据类型分为基本数据类型和引用数据类型。
  • 在 Groovy 中,如果使用了一个明确的数据类型关键字,比如:int ,是可以更改类型的。
  • 示例:
  1. package com.github.fairy.era
  2. int num = 10
  3. num = 3.14
  4. println num // 3,由于此时使用了 int 关键字定义了 num ,即便将浮点数赋值给 num ,也不会保留小数,语法不会报错

2.6 设置类型

  • 使用 def 关键字定义变量是最简单的做法,但是,有的时候我们也需要为其设置具体的类型。
  • 由于在 Groovy 之中所有的单引号或双引号定义的结构都是字符串,如果直接使用单引号,是无法定义字符常量的:
  1. package com.github.fairy.era
  2. def c1 = '我'
  3. println '字符常量 c1 对应的类型:' + c1.getClass() // 字符常量 c1 对应的类型:class java.lang.String
  • 如果说,此时希望将 c1 变量定义为字符,而不是字符串类型,就可以通过 as 数据类型(包括基本类型和包装类型) 设置指定变量的类型。
  1. package com.github.fairy.era
  2. def c1 = '我' as char
  3. def c2 = '我' as Character
  4. println '字符常量 c1 对应的类型:' + c1.getClass() // 字符常量 c1 对应的类型:class java.lang.Character
  5. println '字符常量 c2 对应的类型:' + c2.getClass() // 字符常量 c2 对应的类型:class java.lang.Character

2.7 数据溢出

  • 在 使用 Java 编程的时候,如果操作的数值已经超过了其保存的范围就会产生数据溢出,那么在 Groovy 中是如何解决这个问题的?
  1. package com.github.fairy.era
  2. def numA = Integer.MAX_VALUE + 1 // 整型的最大值 + 1
  3. println 'numA 的内容是:' + numA + '、numA 的类型是:' + numA.class // numA 的内容是:-2147483648、numA 的类型是:class java.lang.Integer,数据溢出了
  4. def numB = 2147483648 + 10 // 已经超过了整型的最大值,自动使用 Long
  5. println 'numB 的内容是:' + numB + '、numB 的类型是:' + numB.class // numB 的内容是:2147483658、numB 的类型是:class java.lang.Long,没有产生数据溢出
  6. def numC = 92233720368547758071223 // 已经超过了 Long 的最大类型
  7. println 'numC 的内容是:' + numC + '、numC 的类型是:' + numC.class // numC 的内容是:92233720368547758071223、numC 的类型是:class java.math.BigInteger,没有产生数据溢出
  • 如果说原始的 Java 编程开发里面有各种各样的限制,但是这些限制在 Groovy 中已经不复存在了,在 Groovy 中程序的编写更加灵活,不会受到各种严苛语法的限制。

2.8 强制类型

  • 在使用 Java 进行编程的时候存在着各种强制性的类型转换,如:LF 等,在 Groovy 中也是存在的,如:
  • ① BigInteger、BigDecimal 使用字母 Gg
  • ② Integer 使用字母 Ii
  • ③ Long 使用字母 Ll
  • ④ Float 使用字母 Ff
  • ⑤ Double 使用字母 Dd

  • 示例:

  1. package com.github.fairy.era
  2. def num1 = 12G
  3. println 'num1 的内容是:' + num1 + '、num1 的类型是:' + num1.class // num1 的内容是:12、num1 的类型是:class java.math.BigInteger
  4. def num2 = 12I
  5. println 'num2 的内容是:' + num2 + '、num2 的类型是:' + num2.class // num2 的内容是:12、num2 的类型是:class java.lang.Integer
  6. def num3 = 12L
  7. println 'num3 的内容是:' + num3 + '、num3 的类型是:' + num3.class // num3 的内容是:12、num3 的类型是:class java.lang.Long
  8. def num4 = 12F
  9. println 'num4 的内容是:' + num4 + '、num4 的类型是:' + num4.class // num4 的内容是:12.0、num4 的类型是:class java.lang.Float
  10. def num5 = 12D
  11. println 'num5 的内容是:' + num5 + '、num5 的类型是:' + num5.class // num5 的内容是:12.0、num5 的类型是:class java.lang.Double

第三章:Groovy 程序逻辑结构

3.1 概述

  • 不论哪种编程语言,都会提供三种基本的流程控制结构:顺序结构、分支结构和循环结构,Groovy 本身继承了 Java 和 Python 的特点,同时里面也有各种所谓的 不重复原则 的设计,那么其所提供的逻辑结构会更加便利。

3.2 循环结构

  • 示例:while 循环
  1. package com.github.fairy.era
  2. def sum = 0 // 保存最终计算的结果
  3. def i = 1
  4. while (i <= 100) {
  5. sum += i
  6. i ++
  7. }
  8. println '从 1 加到 100 的和是:' + sum // 从 1 加到 100 的和是:5050
  • 示例:for 循环
  1. package com.github.fairy.era
  2. def sum = 0
  3. for (def i = 1; i <= 100; i++) {
  4. sum += i
  5. }
  6. println '从 1 加到 100 的和是:' + sum // 从 1 加到 100 的和是:5050

3.3 分支结构

  • 示例:
  1. package com.github.fairy.era
  2. def sum = 0
  3. for (def i = 1; i <= 100; i++) {
  4. if (i % 2 == 0) {
  5. sum += i
  6. }
  7. }
  8. println '从 1 加到 100 的偶数的和是:' + sum // 从 1 加到 100 的偶数的和是:2550

3.4 断言

  • 在程序逻辑之中提供了一种断言操作,其最大的特点在于:判断某个数据经过若干个处理之后一定是某个值。

  • 示例:

  1. package com.github.fairy.era
  2. def num = 10 // 定义变量
  3. assert num == 100 // 断言失败
  • 在 Java 编程里面,如果要想使用断言,必须在程序执行的时候明确的追加一个启动断言的参数,但是在 Python 里面不需要追加任何的参数断言就可以直接生效。

3.5 三目运算符

  • 三目运算符在传统的 Java 项目开发过程中也是一种非常频繁的操作,可以用来简化程序的判断逻辑语句的行数,Groovy 中对其进行了继承并进一步的优化。

  • 示例:

  1. package com.github.fairy.era
  2. def message = null
  3. println '【原始】 message = ' + message // 【原始】 message = null
  4. println '【三目】 message = ' + (message != null ? message : '许大仙') // 【三目】 message = 许大仙,传统的三目运算
  5. // 在 Groovy 编程之中,null 可以直接转换为 false
  6. println '【Groovy】 message = ' + (message ? message : '许大仙') // 【Groovy】 message = 许大仙
  7. // 在 Groovy 中存在有一种“不重复”的原则,可以利用 elvis 操作符进行进一步简化
  8. println '【Groovy】 message = ' + (message ?: '许大仙') // 【Groovy】 message = 许大仙

3.5 范围循环

  • 在 Python 编程里面可以针对一组数据的范围进行循环的处理逻辑,而这样的操作在 Groovy 中也是可以实现的。

  • 示例:

  1. package com.github.fairy.era
  2. def sum = 0
  3. for(x in 1..100){
  4. sum += x
  5. }
  6. println sum // 5050

3.6 迭代操作

  • 如果说现在已经有了一个范围,那么也可以利用 Groovy 提供的 each() 函数设置一个循环的处理。

  • 示例:

  1. package com.github.fairy.era
  2. ('a'..'z').each {// 需要接收一个闭包处理逻辑,其中每个当前的参数使用 it 描述
  3. print it + '、' // a、b、c、d、e、f、g、h、i、j、k、l、m、n、o、p、q、r、s、t、u、v、w、x、y、z、
  4. }

3.7 switch 范围

  • 在传统的 Java 开发中,switch 主要用来做内容判断(如:整型、字符型、枚举、字符串、yield),却并没有范围的匹配,而在 Groovy 中有了这样的处理支持。

  • 示例:

  1. package com.github.fairy.era
  2. def age = 18 // 年龄
  3. switch (age) {
  4. case 0..17:
  5. println '未成年'
  6. break
  7. case 18..30:
  8. println '青年'
  9. break
  10. case 31..60:
  11. println '中年'
  12. break
  13. default:
  14. println '老年'
  15. break
  16. }

第四章:Groovy 方法定义

4.1 概述

  • Groovy 是一门脚本编程语言,但是这个脚本编程语言中融入了 Java 和 Python 的技术特点,那么就可以在程序中实现自定义方法(函数)。

注意:一般将类中的结构称为方法,将类外的结构称为函数,Java 中的程序都是以类为单位执行的,所以就都是方法了,而在 Python 里面,有部分函数是定义在类外面的,这部分就不是方法了。

4.2 定义方法

  • 在 Groovy 中所有的方法都是采用运行时分配的处理机制,即所有传递到方法中的参数都是根据输入数据的类型来进行判断的。

  • 示例:

  1. package com.github.fairy.era
  2. public String method(String msg) {
  3. return "【String参数】msg = " + msg
  4. }
  5. public String method(Object msg) {
  6. return "【Object参数】msg = " + msg
  7. }
  8. println method('你好啊') // 【String参数】msg = 你好啊
  9. println method(new Object()) // 【Object参数】msg = java.lang.Object@12d2ce03
  • 此时,如果按照传统的面向对象的程序设计,一般都是采用向上转型的模式(随着 JDK 版本的升级,这种方式也修改了,早期都是向上转型的),在 Groovy 里面可以明确的区分不同类型的参数而进行动态的匹配。

4.3 闭包操作

  • 闭包相当于定义了一个描述函数的变量(函数名称)。

  • 示例:简单闭包

  1. package com.github.fairy.era
  2. def method = { -> // 如果没有参数,可以简化此符号
  3. return "你好啊"
  4. }
  5. println "闭包的返回结果:" + method() + ",闭包的类型:" + method.class // 闭包的返回结果:你好啊,闭包的类型:class com.github.fairy.era.HelloGroovy$_run_closure1
  • 在进行闭包结构的处理之中,就像一个普通的函数进行了变量的调用,但是其对应的类型是 Closure 。

  • 示例:闭包参数

  1. package com.github.fairy.era
  2. def method = { int ... args -> // 可变参数
  3. def all = 0
  4. for(def num : args){
  5. all += num
  6. }
  7. return all
  8. }
  9. println "闭包的返回结果:" + method(1,2,3) + ",闭包的类型:" + method.class // 闭包的返回结果:6,闭包的类型:class com.github.fairy.era.HelloGroovy$_run_closure1
  • 当前参数:

    • 在进行函数定义的时候一般都可以采用一种当前参数的形式,这种当前参数就是通过 it 进行描述,利用这样的函数可以简化一些参数的定义。
    • it 是在 Groovy 之中默认提供的一个当前的参数信息,如果现在有传递的参数内容,it 描述的就是当前的参数内容;如果没有参数进行传递,则 it 的内容就是 null 。
  • 示例:

  1. package com.github.fairy.era
  2. def method = {
  3. return '【ECHO】当前参数:' + it
  4. }
  5. println method() // 【ECHO】当前参数:null
  6. println method.call(1) // 【ECHO】当前参数:1
  • 直接返回:如果此时一个闭包处理的函数之中只有一个要返回的语句,那么就直接编写内容即可(可以省略 return)。

  • 示例:

  1. package com.github.fairy.era
  2. def method = {
  3. '【ECHO】当前参数:' + it
  4. }
  5. println method() // 【ECHO】当前参数:null
  6. println method.call(1) // 【ECHO】当前参数:1
  • main 方法:

    • Java 程序都是通过 主方法开始执行的,但是,在 Python 中不受到这样的局限的(在 Python 里面往往为了清楚的描述出结构,也会加上一个主方法),在 Groovy 中也可以定义主方法,只需要使用 static 开头即可。
    • Groovy 在定义的时候完全吸收了 Python 的风格,所以是否一定要定义方法并不是强制要求,毕竟 Groovy 是一个基于 Java 实现的 Python 语法风格的脚本编程语言。
  • 示例:

  1. package com.github.fairy.era
  2. static void main(String[] args) { // 主方法
  3. def method = {
  4. '【ECHO】参数:' + it
  5. }
  6. println method('你好,Groovy') // 【ECHO】参数:你好,Groovy
  7. }

第五章:Groovy 数据集合

5.1 概述

  • 程序中的集合主要是由数组、列表、Map 来描述的,在 Groovy 中如果要想定义这些结构是非常容易的。

5.2 数组

  • 在 Java 中数组提供了一个 java.util.Arrays 工具类来进行数组的各种操作。

  • 示例:

  1. package com.github.fairy.era
  2. int[] nums = new int[]{5, -10, 60, 4, 99} // 定义数组
  3. Arrays.sort(nums) // 数组排序
  4. println '数组的直接输出:' + nums // 数组的直接输出:[-10, 4, 5, 60, 99]
  5. println 'Arrays 实现数组的输出:' + Arrays.toString(nums) // Arrays 实现数组的输出:[-10, 4, 5, 60, 99]
  6. println '获取数组的长度:' + nums.length // 获取数组的长度:5

5.3 列表定义

  • 实际上在实际开发中,Java 里面所有的数组都会以 List 的形式来进行描述(Python 中没有提供数组的定义就在于此)。

  • 示例:

  1. package com.github.fairy.era
  2. def messages = ['Java 从入门到精通', 'C 从入门到入土', 'PHP 是世界上最好的语言'] // 定义 List
  3. messages << 'Java 从入门到入土' // 相当于 message.add() 的语法操作
  4. println '【列表的内容】==> ' + messages // 【列表的内容】==> [Java 从入门到精通, C 从入门到入土, PHP 是世界上最好的语言, Java 从入门到入土]
  5. println '【列表的类型】==> ' + messages.class // 【列表的类型】==> class java.util.ArrayList
  6. println '【列表部分数据】==> ' + messages[0, 2, 3] // 【列表部分数据】==> [Java 从入门到精通, PHP 是世界上最好的语言, Java 从入门到入土]
  • 迭代输出:

    • 此时已经获取到了列表(在实际开发中一般都会通过列表来代替数组),那么一定要进行列表内容的输出,此时可以考虑使用 each() 函数的结构来完成。
    • 列表在一些开发中实际上是横向替代数组的结构,那么既然要进行横向数组的替代,就应该考虑到数组对应的索引,如果要想基于索引的方式进行操作,就需要使用 eachWithIndex() 函数来完成。
  • 示例:

  1. package com.github.fairy.era
  2. def messages = ['Java 从入门到精通', 'C 从入门到入土', 'PHP 是世界上最好的语言'] // 定义 List
  3. messages.each {
  4. println '[列表内容] ' + it
  5. }
  • 示例:
  1. package com.github.fairy.era
  2. def messages = ['Java 从入门到精通', 'C 从入门到入土', 'PHP 是世界上最好的语言']
  3. messages.eachWithIndex { String it, int index ->
  4. println '【索引】' + index + ',【内容】' + it
  5. }
  • Set 集合:既然已经有了 List 集合,那么就不得不思考如何去定义 Set 集合,在 Groovy 之中,Set 集合的定义形式和 List 集合的差别不大,唯一的区别就是需要手工的方式为其设置具体的类型定义。

  • 示例:

  1. package com.github.fairy.era
  2. def book = ['Java 从入门到精通', 'C 从入门到入土', 'PHP 是世界上最好的语言', 'C 从入门到入土'] as Set
  3. book.eachWithIndex { String it, int index ->
  4. println '【索引】' + index + ',【内容】' + it
  5. }

5.4 Map 映射

  • 和 List、Set 不同的是,Map 集合可以通过 key 来实现 value 的获取,在定义的时候可以直接通过 key:value 的方式来定义多个映射项。

  • 示例:

  1. package com.github.fairy.era
  2. def book = ['Java': '20元', 'C': '50元']
  3. println '根据 key 获取 value:' + book['Java']
  4. println '根据 key 获取 value:' + book.C
  • 迭代输出:Map 也可以使用迭代的方式进行输出的处理。

  • 示例:

  1. package com.github.fairy.era
  2. def book = ['Java': '20元', 'C': '50元']
  3. book << ['PHP': '100元']
  4. book.each { it ->
  5. println 'key ==> ' + it.getKey() + ',value ==> ' + it.getValue()
  6. }

第六章:Groovy 字符串

6.1 概述

  • 在 Groovy 之中字符串的定义逻辑是非常简单的,可以使用单引号或双引号来完成,这一点和 Python 的设计是非常类似的,但是除了这些之外,Groovy 里面对于字符串的支持也是比较到位的。

6.2 字符串比较

  • 传统 Java 中字符串的比较是通过 equals() 方法来进行比较的,但是,在 Groovy 中却可以通过 == 运算符进行比较(区分大小写)。

  • 示例:

  1. package com.github.fairy.era
  2. def s1 = 'Java'
  3. def s2 = 'Java'
  4. def s3 = 'java'
  5. println '【==】比较' + (s1 == s2) // 【==】比较true
  6. println '【equals】比较' + (s1.equals(s2)) // 【equals】比较true
  7. println '【==】比较' + (s2 == s3) // 【==】比较false
  8. println '【equals】比较' + (s2.equals(s3)) // 【equals】比较false

6.3 文本块

  • 在 JDK 13 中引入了文本块的概念,在 Groovy 中同样提供了此功能。

  • 示例:

  1. package com.github.fairy.era
  2. def str = '''
  3. Java 牛逼
  4. Groovy 很好啊
  5. IDEA 真香
  6. '''
  7. println str
  • 对于上面的程序代码可以非常清楚的发现,所有的字符串中定义的结构被完整的保留了下来,所以这样的操作相当于实现了预定义结构模式,但是如果不想让第一行出现空格,那么可以在字符串中插入 \

  • 示例:

  1. package com.github.fairy.era
  2. def str = '''\
  3. Java 牛逼
  4. Groovy 很好啊
  5. IDEA 真香
  6. '''
  7. println str

6.4 插值字符串

  • 在使用 Java 进行若干个字符串连接的时候最无奈的事情就是编写大量的 + 实现连接,但是在 Groovy 中考虑到用户的实际使用情况,已经提供了另外一种字符串的结构:插值字符串,这种结构最大的特点就在于,可以直接将所需要替换的变量定义在字符串之中。

  • 示例:

  1. package com.github.fairy.era
  2. def str1 = '我' // 变量
  3. def str2 = '很' // 变量
  4. def str3 = '好' // 变量
  5. // 插值填充的时候必须使用双引号,对应的类型为 groovy.lang.GString(插值字符串类型)
  6. def str = "${str1}${str2}${str3}"
  7. println str // 我很好
  8. println str.getClass() // class org.codehaus.groovy.runtime.GStringImpl
  • Map 填充:以上的代码是将所有可能使用到的字符串信息全部定义在变量里面,这样就会导致定义的变量太多,那么就可以考虑将填充的内容直接放到 Map 集合中。

  • 示例:

  1. package com.github.fairy.era
  2. def map = [school: '江苏苏州大学', address: '江苏省苏州市工业园区xxx', age: 18]
  3. def message = "学校:${map.school},地址:${map.address},年龄:${map.age}"
  4. println "【模式一】${message}" // 【模式一】学校:江苏苏州大学,地址:江苏省苏州市工业园区xxx,年龄:18
  5. message = "学校:$map.school,地址:$map.address,年龄:$map.age"
  6. println "【模式二】${message}" // 【模式二】学校:江苏苏州大学,地址:江苏省苏州市工业园区xxx,年龄:18

6.5 正则匹配

  • 在字符串定义的时候依然可以像传统 Java 那样操作正则表达式。

  • 示例:

  1. package com.github.fairy.era
  2. def pattern = /\d+/ // 定义正则表达式
  3. println "123".matches(pattern) // true

第七章:Groovy 类结构操作

7.1 概述

  • Groovy 是针对于 Java 程序的一种 Python 封装,所以在 Groovy 中也可以直接定义所需要的程序类。

7.2 类定义

  • 按照传统的类定义,类中只有定义了构造方法之后才可以实现属性内容的自动赋值,但是在 Groovy 里面可以发现构造方法不需要强制性的进行定义,只要在使用的时候根据属性的要求设置相应的内容即可,同时在获取属性的时候想要通过 getter 方法进行获取,直接使用 @属性名称 的结构来完成。

  • 示例:

  1. package com.github.fairy.era
  2. /**
  3. * ① Groovy 中默认都是 public 的。
  4. * ② 所有的 Groovy 类默认都集成了一个 GroovyObject 的类。
  5. * 上面的两点和 Java 不同。
  6. */
  7. class Message { // 定义一个程序类
  8. protected String content // 消息的内容
  9. def getContent() { // Groovy 中的方法定义语法
  10. return this.content
  11. }
  12. }
  13. def message = new Message(content: '你好,Groovy') // 构造方法设置内容
  14. // 在 Groovy 中直接通过.操作符操作的并不是对象的属性,实际上是调用 getXxx() 方法。
  15. println '传统的获取 Content 属性:' + message.content // 传统的获取 Content 属性:你好,Groovy。
  16. println 'Groovy 语法获取 Content 属性:' + message.@content // Groovy 语法获取 Content 属性:你好,Groovy

7.3 对象集合

  • 既然可以直接实例化一个类对象,那么就可以实例化多个类对象信息,并且将其设置到 List 集合之中。

  • 示例:

  1. package com.github.fairy.era
  2. class Message { // 定义一个程序类
  3. protected String content // 消息的内容
  4. def getContent() { // Groovy 中的方法定义语法
  5. return this.content
  6. }
  7. }
  8. def list = [new Message(content: '你好'), new Message(content: 'Groovy')]
  9. list.each {
  10. print it.content + '、' // 你好、Groovy、
  11. }
  • 在 Groovy 里面如果有集合了,也可以考虑通过集合输出里面全部对象中的指定属性的信息。

  • 示例:

  1. package com.github.fairy.era
  2. class Message { // 定义一个程序类
  3. protected String content // 消息的内容
  4. def getContent() { // Groovy 中的方法定义语法
  5. return this.content
  6. }
  7. }
  8. def list = [new Message(content: '你好'), new Message(content: 'Groovy')]
  9. println list*.content

第八章:Groovy 文件操作

8.1 概述

  • Groovy 中的文件操作也是针对于 Java 中文件操作的各种包装,而且在以后编写 Gradle 项目脚本的时候也一定会牵扯到文件的处理操作,如:在进行项目打包的时候有可能需要将一些固定目录中的内容进行输出,那么此时就需要进行文件的 IO 处理。

8.2 文件的写入

  • 既然要进行文件的输出,那么首先就需要考虑的是文件的写入操作,传统的 IO 的写入非常的繁琐,但是在 Groovy 里面可以直接通过非常简单的各种函数来实现。

  • 示例:

  1. package com.github.fairy.era
  2. // 当前要操作的父目录
  3. def baseDir = new File('G:' + File.separator)
  4. // 文件的写入
  5. new File(baseDir, 'message.txt').withWriter('UTF-8', { writer ->
  6. writer.writeLine("你好啊,Groovy")
  7. writer.writeLine("SpringBoot 真香")
  8. })

8.3 文件读取

  • 既然可以实现文件的简化输出操作,那么也一定可以实现文件的简化读取操作,如果要进行文件读取,是根据每一行的形式进行读取的。

  • 示例:

  1. package com.github.fairy.era
  2. // 当前要操作的父目录
  3. def baseDir = new File('G:' + File.separator)
  4. // 文件的读取
  5. new File(baseDir, 'message.txt').eachLine ({ data,line ->
  6. println "【${line}】" + data
  7. })

8.4 目录遍历

  • 除了进行基本的文件读取之外,在实际的开发之中还可能需要对文件的目录进行遍历,那么此时可以直接通过 File 对象实现此功能。

  • 示例:

  1. package com.github.fairy.era
  2. // 当前要操作的父目录
  3. def baseDir = new File('G:' + File.separator)
  4. // 对目录进行遍历
  5. baseDir.eachFileMatch(~/.*\.txt/,{file ->
  6. println file.name
  7. })

第九章:Groovy 多线程

9.1 概述

  • 在传统的 Java 开发过程中,如果使用多线程,通常先定义线程的主体类,然后再去使用一些线程相关的工具(如:JUC),但是在 Groovy 里面由于需要按照 Python 脚本的编写形式,所以对于多线程的实现也得到了部分的简化。

9.2 多线程的实现

  • 不管如何改变代码的结构,多线程的实现还是需要按照 Java 的实现方式,即 Thread 类来完成。

  • 示例:

  1. package com.github.fairy.era
  2. println '【主线程】' + Thread.currentThread().getName() // 【主线程】main
  3. Thread.start {
  4. println '【子线程】' + Thread.currentThread().getName() // 子线程的名称,【子线程】Thread-1
  5. '你好啊,Groovy'.each { // 对每个字符进行遍历
  6. print it + '、' // 你、好、啊、,、G、r、o、o、v、y、
  7. }
  8. }

9.4 Timer 线程

  • 在 Java 程序开发的过程中提供了一种定时任务,我们就可以通过定时任务创建子线程。

  • 示例:

  1. package com.github.fairy.era
  2. new Timer().runAfter(1000, {
  3. for (def x = 0; x < 10; x++) {
  4. print '【' + Thread.currentThread().getName() + '】' + x + '、'
  5. }
  6. })

9.5 线程同步

  • 既然有了多线程的处理,那么一定会存在有线程同步的操作机制。

  • 示例:

  1. package com.github.fairy.era
  2. def tickets = 10 // 总票数
  3. def sale = {
  4. synchronized (this) { // 同步代码块
  5. sleep(100) // 模拟延迟
  6. println '【' + Thread.currentThread().getName() + '】卖票,当前剩余的票数:' + tickets--
  7. }
  8. }
  9. for (x in 1..10) { // 模拟卖票
  10. def start = Thread.start(sale)
  11. start.name = '售票员 - ' + x
  12. }

9.6 线程池

  • 为了进一步方便线程资源的管理,肯定所有的线程都要放在线程池中最为方便了。

  • 示例:

  1. package com.github.fairy.era
  2. import java.util.concurrent.Executors
  3. // 当前电脑硬件所有可分配的CPU数量全部分配给了线程池
  4. def pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors())
  5. for (x in 1..20) {
  6. pool.submit(() -> {
  7. println '【' + Thread.currentThread().getName() + '】' + '你好,Groovy'
  8. })
  9. }