Groovy语言详解

2023-10-26

一、Groovy 概述

Groovy是一种基于Java平台的面向对象语言。 Groovy 1.0于2007年1月2日发布,其中Groovy 2.4是当前的主要版本。 Groovy通过Apache License v 2.0发布。

Groovy中有以下特点:

  • 同时支持静态和动态类型。
  • 支持运算符重载。
  • 本地语法列表和关联数组。
  • 对正则表达式的本地支持。
  • 各种标记语言,如XML和HTML原生支持。
  • Groovy对于Java开发人员来说很简单,因为Java和Groovy的语法非常相似。
  • 您可以使用现有的Java库。
  • Groovy扩展了java.lang.Object。

Groovy的官方网站是The Apache Groovy programming language

二、Groovy 环境部署

有多种方式来获得的Groovy环境设置。

下载和安装: -进入该链接www.groovy-lang.org/download.html获得Windows安装程序部分。

启动Groovy安装程序,然后请执行以下完成安装步骤。

第1步 -选择语言安装程序

第2步 -点击下一步按钮 

第3步 -点击“我同意”按钮

第4步 -接受默认组件,然后单击下一步按钮 

第5步 -选择适当的目标文件夹,然后单击下一步按钮

第6步 -点击安装按钮开始安装

第7步 -一旦安装完成后,单击下一步按钮开始配置 

第8步 -选择默认选项,并单击下一步按钮

第9步 -接受默认的文件关联,然后单击下一步按钮

第10步 -单击Finish按钮完成安装 

一旦上述步骤之后,你就可以开始使用Groovy shell,有助于测试我们的Groovy,而不需要为Groovy提供一个完整的集成开发环境。可以通过在命令提示符下命令groovysh来完成。 

如果你想包含groovy二进制文件作为maven或gradle构建的一部分,你可以添加以下行。

Gradle:

'org.codehaus.groovy:groovy:2.4.5'

Maven:

<groupId>org.codehaus.groovy</groupId> 
<artifactId>groovy</artifactId>  
<version>2.4.5</version>

三、Groovy 基本语法

为了了解 Groovy 的基本语法,让我们先看看一个简单的 Hello World 程序。

1、Hello World 程序

创建Hello World程序,你只要输入以下几行简单的代码就可实现 -

class Example {
   static void main(String[] args) {
      // Using a simple println statement to print output to the console
      println('Hello World');
   }
}

当我们运行上面的程序,我们会得到以下结果 -

Hello World

2、在 Groovy 中导入语句

import 语句可以用来导入,可以让你的代码使用其他库的功能。这是通过使用在 Import 关键字完成。

下面的示例演示了如何使用 MarkupBuilder 的类,它可能是最常用的创建 HTML 或 XML 标记的类之一。

import groovy.xml.MarkupBuilder 
def xml = new MarkupBuilder() 

默认情况下,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

3、Groovy 令牌

令牌可以是一个关键字,一个标识符,常量,字符串文字或符号。

println(“Hello World”);

在上面的代码行中,有两个令牌,首先是关键词的 println 而接下来就是字符串的“Hello World”。

4、Groovy 注释

在您的代码中使用注释。Groovy 的注释可以是单行或多行。

单行注释使用 // 在该行的任何位置来识别。一个例子如下所示 -

class Example {
   static void main(String[] args) {
      // Using a simple println statement to print output to the console
      println('Hello World');
   }
}

多行注释标识与在开始 / * 和 * / 识别多行注释的末尾。

class Example {
   static void main(String[] args) {
      /* This program is the first program
      This program shows how to display hello world */
      println('Hello World');
   }
}

5、分号

就像 Java 编程语言,它需要具有分号在 Groovy 定义多个语句之间进行区分。

class Example {
   static void main(String[] args) {
      // One can see the use of a semi-colon after each statement
      def x = 5;
      println('Hello World');  
   }
}

上述例子示出了分号使用了不同行的代码语句之间进行区分。

6、身份标识

标识符被用来定义变量,函数或其他用户定义的变量。标识符以字母开头,美元或下划线。他们不能以数字开头。以下是有效标识符的一些例子 

def employeename 
def student1 
def student_name

其中DEF 是在 Groovy 用来定义标识符的关键字。

下面是一个如何在我们的 Hello World 程序中使用标识符的代码示例。

class Example {
   static void main(String[] args) {
      // One can see the use of a semi-colon after each statement
      def x = 5;
      println('Hello World'); 
   }
}

在上述的例子中,变量 被用作标识符。

7、关键词

关键字作为名称建议是在 Groovy 编程语言中保留的特殊字。 下表列出了在 Groovy 中定义的关键字。

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

8、空白

空白是在编程语言如 Java 和 Groovy 用来形容空格,制表符,换行符和注释术语。空格分隔从另一个声明的一部分,使编译器,其中一个元素标识的声明。

例如,在下面的代码示例,存在关键字 def 和变量 x 之间的空白。这是为了让编译器知道 DEF 是需要被使用,并且是 x 应该是需要被定义的变量名的关键字。

def x = 5;

9、文字

文字是在 groovy 中表示固定值的符号。Groovy 语言有符号整数,浮点数,字符和字符串。下面是一些在 Groovy 编程语言文字的例子 -

12 
1.45 
‘a’ 
“aa”

四、Groovy 数据类型

在任何编程语言中,需要使用各种变量来存储各种类型的信息。变量只是保留值的存储位置,这意味着,当你创建一个变量,你保留在内存中的一些空间来存储与变量相关的值。

您可能喜欢存储各种数据类型的信息,如字符串,字符,宽字符,整数,浮点数,布尔值等。基于变量的数据类型,操作系统分配内存并决定什么可以存储在保留的存储器中。

1、内置数据类型

Groovy提供多种内置数据类型。以下是在Groovy中定义的数据类型的列表 -

  • byte -这是用来表示字节值。例如2。

  • short -这是用来表示一个短整型。例如10。

  • int -这是用来表示整数。例如1234。

  • long -这是用来表示一个长整型。例如10000090。

  • float -这是用来表示32位浮点数。例如12.34。

  • double -这是用来表示64位浮点数,这些数字是有时可能需要的更长的十进制数表示。例如12.3456565。

  • char -这定义了单个字符文字。例如“A”。

  • Boolean -这表示一个布尔值,可以是true或false。

  • String -这些是以字符串的形式表示的文本。例如,“Hello World”的。

2、绑定值

下表显示了数字和小数点文字中的最大允许值。

byte -128到127
short -32,768到32,767
int -2,147,483,648到2,147,483,647
long -9,223,372,036,854,775,808到+9,223,372,036,854,775,807
float 1.40129846432481707e-45到3.40282346638528860e + 38
double 4.94065645841246544e-324d 到1.79769313486231570e + 308d

3、数字类

类型除了基本类型,还允许以下对象类型(有时称为包装器类型)-

  • java.lang.Byte
  • java.lang.Short
  • java.lang.Integer
  • java.lang.Long
  • java.lang.Float
  • java.lang.Double

此外,以下类可用于支持高精度计算 -

名称 描述 例如
java.math.BigInteger 不可变的任意精度的有符号整数数字 30克
java.math.BigDecimal 不可变的任意精度的有符号十进制数 3.5克

以下代码示例说明如何使用不同的内置数据类型 -

class Example { 
   static void main(String[] args) { 
      //Example of a int datatype 
      int x = 5; 
		
      //Example of a long datatype 
      long y = 100L; 
		
      //Example of a floating point datatype 
      float a = 10.56f; 
		
      //Example of a double datatype 
      double b = 10.5e40; 
		
      //Example of a BigInteger datatype 
      BigInteger bi = 30g; 
		
      //Example of a BigDecimal datatype 
      BigDecimal bd = 3.5g; 
		
      println(x); 
      println(y); 
      println(a); 
      println(b); 
      println(bi); 
      println(bd); 
   } 
}

当我们运行上面的程序,我们会得到以下结果 -

5 
100 
10.56 
1.05E41 
30 
3.5

五、Groovy 变量

Groovy中的变量可以通过两种方式定义 - 使用数据类型的本地语法,或者使用def关键字。对于变量定义,必须明确提供类型名称或在替换中使用“def”。这是Groovy解析器需要的。

Groovy中有以下基本类型的变量,如上一章所述 -

  • byte - 这用于表示字节值。例如2。

  • short - 用于表示一个短数。例如10。

  • int - 这用于表示整数。 例如1234。

  • long - 这用于表示一个长数。例如10000090。

  • float - 用于表示32位浮点数。例如12.34。

  • double - 这用于表示64位浮点数。例如12.3456565。

  • char - 这定义了单个字符文字。例如'a'。

  • Boolean - 这表示一个布尔值,可以是true或false。

  • String - 这是以字符串形式表示的文本。 例如“Hello World”。

Groovy还允许其他类型的变量,如数组,结构和类,我们将在后续章节中看到。

1、变量声明

变量声明告诉编译器为变量创建存储的位置和大小。

下面是一个变量声明的例子 -

class Example { 
   static void main(String[] args) { 
      // x is defined as a variable 
      String x = "Hello";
		
      // The value of the variable is printed to the console 
      println(x);
   }
}

当我们运行上面的程序,我们会得到以下结果 -

Hello

2、变量命名

变量的名称可以由字母,数字和下划线字符组成。 它必须以字母或下划线开头。 大写和小写字母是不同的,因为Groovy,就像Java是一种区分大小写的编程语言。

class Example { 
   static void main(String[] args) { 
      // Defining a variable in lowercase  
      int x = 5;
	  
      // Defining a variable in uppercase  
      int X = 6; 
	  
      // Defining a variable with the underscore in it's name 
      def _Name = "Joe"; 
		
      println(x); 
      println(X); 
      println(_Name); 
   } 
}

当我们运行上面的程序,我们会得到以下结果 -

5 
6 
Joe 

我们可以看到x和X是两个不同的变量,因为区分大小写,在第三种情况下,我们可以看到_Name以下划线开头。

3、打印变量

您可以使用println函数打印变量的当前值。下面的示例显示了如何实现这一点。

class Example { 
   static void main(String[] args) { 
      //Initializing 2 variables 
      int x = 5; 
      int X = 6; 
	  
      //Printing the value of the variables to the console 
      println("The value of x is " + x + "The value of X is " + X);  
   }
}

当我们运行上面的程序,我们会得到以下结果 -

The value of x is 5 The value of X is 6 

六、Groovy 运算符

运算符是一个符号,通知编译器执行特定的数学或逻辑操作。

Groovy中有以下类型的运算符 -

  • 算术运算符
  • 关系运算符
  • 逻辑运算符
  • 位运算符
  • 赋值运算符

1、算术运算符

Groovy语言支持正常的算术运算符任何语言。

以下是在Groovy中可用的算术运算符:

运算符 描述 例子
+ 两个操作数的加法 1 + 2 将得到 3
- 第一第二操作数相减 2 - 1 将得到 1
* 两个操作数的乘法 2 * 2 将得到4 
/ 两个操作数的除法 3/2 将得到 1.5
取模运算 3%2 将得到 1
++ 自增运算,在自身值的基础上加1

INT X = 5;

X ++;

X 将得到 6

-- 自减运算,在自身值的基础上减1

INT X = 5;

X - -;

X 将得到 4

2、关系运算符

关系运算符允许对象的比较。

以下是在Groovy中可用的关系运算符:

运算符 描述 例子
== 测试两个对象之间是否相等 2 == 2 将得到 true
!= 测试两个对象之间是否不等 3 != 2 将得到 true
< 检查是否左边的对象是小于右边的对象。 2 < 3 将得到 true
<= 检查是否向左对象是小于或等于右边的对象 2 <= 3 将得到 true
> 检查是否左边的对象比右边的对象大。 3 > 2 将得到 true
>= 检查是否向左对象大于或等于右边的对象。 3>= 2 将得到 true

3、逻辑运算符

逻辑运算符用于计算布尔表达式。

以下是在Groovy中提供的逻辑运算符:

运算符 描述 例子
&& 这是逻辑“与”运算 true && true 得到 true
|| 这是逻辑“或”运算 true || true 得到 true
这是逻辑“非”运算 !true 得到 false

4、位运算符

Groovy中提供了四个位运算符。

以下是在Groovy中可用的位运算符:

运算符 描述
这是位“与”运算
| 这是按位“或”运算
^ 这是按位“异或”或异或运算符
这是按位反运算符

这里是显示这些运算符的真值表:

p q p&Q p | q p ^ Q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

5、赋值运算符

Groovy语言也提供了赋值操作符。

以下是在Groovy提供的赋值运算符:

运算符 描述 例子
+= A += B 等价于 A = A+B

DEF A = 5

A += 3

输出将是8

-= A -= B 等价于 A = A-B

DEF A = 5

A -= 3

输出将是2

*= A *= B 等价于 A= A*B

DEF A = 5

A *= 3

输出将是15

/= A /= B 等价于 A = A/B

DEF A = 6

A /= 3

输出将是2

(%)= A (%)= B 等价于 A = A % B

DEF A = 5

A %= 3

输出将是2

6、范围运算符

Groovy支持范围的概念,并在..符号的帮助下提供范围运算符的符号。下面给出了范围运算符的一个简单示例。

<span style="background-color:#201e2f"><span style="color:#f8f8f2"><code>def range = 0..5 
</code></span></span>

这只是定义了一个简单的整数范围,存储到一个局部变量称为范围内的下限为0和上限为5。

以下代码段显示了如何使用各种运算符。

<span style="background-color:#201e2f"><span style="color:#f8f8f2"><code>class Example { 
   static void main(String[] args) { 
      def range = 5..10; 
      println(range); 
      println(range.get(2)); 
   } 
}
</code></span></span>

当我们运行上面的程序,我们会得到以下结果 -

从println语句中,可以看到显示在range语句中定义的整个数字范围。

get语句用于从定义的范围中获取一个对象,它将索引值作为参数。

<span style="background-color:#201e2f"><span style="color:#f8f8f2"><code>[5, 6, 7, 8, 9, 10] 
7
</code></span></span>

7、运算符优先级

下表按优先级顺序列出了所有groovy运算符(仅列出部分运算符):

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

七、Groovy 循环

到目前为止,我们已经看到已经按顺序方式一个接一个执行的语句。此外,在Groovy中提供了语句来改变程序逻辑中的控制流。

然后将它们分类为我们将详细看到的控制语句的流程:

序号 语句和描述
1

​while语句             
while语句首先通过计算条件表达式(布尔值)来执行,如果结果为真,则执行while循环中的语句。

2

​for语句

for语句用于遍历一组值。

3

​for-in语句

for-in语句用于遍历一组值。

循环控制语句:

序号 语句和描述
1

​break语句

break语句用于改变循环和switch语句内的控制流。

2

​continue语句             
continue语句补充了break语句。它的使用仅限于while和for循环。

1、while语句

while语句的语法如下所示 -

while(condition) { 
   statement #1 
   statement #2 
   ... 
}

通过首先计算条件表达式(布尔值)来执行 while 语句,如果结果为true,则执行while循环中的语句。从while语句中的条件的评估开始重复该过程 此循环继续,直到条件计算为false。当条件变为假时,循环终止。 然后程序逻辑继续紧跟在while语句之后的语句。下图显示了此循环的图解说明。

下面是一个while循环语句的例子 -

class Example {
   static void main(String[] args) {
      int count = 0;
		
      while(count<5) {
         println(count);
         count++;
      }
   }
}

在上面的例子中,我们首先将计数整数变量的值初始化为0.然后我们在while循环中的条件是我们计算表达式的条件是计数应该小于5。count小于5,我们将打印count的值,然后增加count的值。上面的代码的输出将是 -

0 
1 
2 
3 
4

2、for语句

for 语句用于遍历一组值。

for 语句通常以以下方式使用:

for(variable declaration;expression;Increment) { 
   statement #1 
   statement #2 
   … 
}

经典的语句包括以下部分:

  • 变量声明 - 此步骤对整个循环只执行一次,用于声明将在循环中使用的任何变量。

  • 表达式 - 这将包含一个表达式,将为循环的每次迭代计算。

  • 增量部分将包含在 for 语句中声明的变量所需的逻辑。

下图显示了此循环的图解说明:

下面是一个经典的语句的例子:

class Example { 
   static void main(String[] args) {
	
      for(int i = 0;i<5;i++) {
	     println(i);
      }
		
   }
}

在上面的例子中,我们在 for 循环中做三件事 -

  • 声明变量 i 并将 i 的值初始化为0

  • 设置 for 循环的条件表达式应该执行,直到i的值小于5。

  • 每次迭代将 i 的值增加1。

上面的代码的输出将是:

0 
1 
2 
3 
4 

3、for-in语句

for-in 语句用于遍历一组值。

for-in 语句通常以以下方式使用:

for(variable in range) { 
   statement #1 
   statement #2 
   … 
}

下图显示了此循环的图解说明:

以下是for-in语句的示例:

class Example { 
   static void main(String[] args) { 
      int[] array = [0,1,2,3]; 
		
      for(int i in array) { 
         println(i); 
      } 
   } 
}

在上面的例子中,我们首先初始化一个具有0,1,2和3的4个值的整数数组。然后我们使用for循环语句首先定义一个变量i,然后遍历数组中的所有整数 并相应地打印值。

上面的代码的输出将是:

0 
1 
2 
3

for-in 语句也可用于循环范围。

以下示例说明如何完成此操作:

class Example {
   static void main(String[] args) {
	
      for(int i in 1..5) {
         println(i);
      }
		
   } 
} 

在上面的例子中,我们实际上循环了从1到5定义的范围,并打印该范围中的每个值。

上面的代码的输出将是:

1 
2 
3 
4 
5 

for-in 语句也可用于循环访问Map。

以下示例说明如何完成此操作:

class Example {
   static void main(String[] args) {
      def employee = ["Ken" : 21, "John" : 25, "Sally" : 22];
		
      for(emp in employee) {
         println(emp);
      }
   }
}

在上面的例子中,我们实际上循环通过一个映射,它有一组定义的键值条目。

上面的代码的输出将是:

Ken = 21 
John = 25 
Sally = 22 

4、break语句

break 语句用于更改loop和switch语句内的控制流。我们已经看到break语句与switch语句结合使用。break语句也可以与while和for语句一起使用。使用这些循环结构中的任何一个执行 break 语句会立即终止最内层的循环。

下图显示了 break 语句的图解说明:

以下是break语句的示例 -

class Example {
   static void main(String[] args) {
      int[] array = [0,1,2,3];
		
      for(int i in array) {
         println(i);
         if(i == 2)
         break;
      }
   } 
}

上面的代码的输出将是 -

0 
1 
2 

正如预期的,因为有一个条件,说如果 i 的值为2,那么从循环中断,这就是为什么不打印数组的最后一个元素为3。

 5、continue语句

continue语句补充了break语句。它的使用局限于while和for循环。当执行continue语句时,控制立即传递到最近的封闭循环的测试条件,以确定循环是否应该继续。对于该特定循环迭代,循环体中的所有后续语句都将被忽略。

下图显示了continue语句的图解说明:

以下是 continue 语句的示例:

class Example {
   static void main(String[] args) {
      int[] array = [0,1,2,3];
		
      for(int i in array) {
         println(i);
         if(i == 2)
         continue;
      }
   }
}

上面的代码的输出将是:

0 
1 
2 
3

八、Groovy 条件语句

条件声明需要程序指定一个或者多个条件进行判断,如果条件被确定为真,则要执行一个或多个语句;如果条件被确定为假,则要执行其他语句。

序号 语句和描述
1

​if语句

这个语句的一般工作是首先在if语句中计算一个条件。如果条件为真,它然后执行语句。

2

​if / else语句

这个语句的一般工作是首先在if语句中计算一个条件。如果条件为真,则其后执行语句,并在else条件之前停止并退出循环。如果条件为假,则执行else语句块中的语句,然后退出循环。

3

​嵌套if语句

i有时需要有多个if语句嵌入在彼此内部。

4

​Switch语句

有时,嵌套的if-else语句是如此常见,并且经常使用,因此设计了一个更容易的语句,称为switch语句。

5

​嵌套switch语句             
switch也可以多层嵌套。

1、​if语句

第一个决策语句是 if 语句。

这种说法的一般形式是:

if(condition) { 
   statement #1 
   statement #2 
   ... 
}

这个语句的一般工作是首先在 if 语句中评估一个条件。如果条件为真,它然后执行语句。

下图显示了 if 语句的流程:

下面是一个if / else语句的例子:

class Example { 
   static void main(String[] args) { 
      // Initializing a local variable 
      int a = 2 
		
      //Check for the boolean condition 
      if (a<100) { 
         //If the condition is true print the following statement 
         println("The value is less than 100"); 
      } 
   } 
}

在上面的例子中,我们首先将一个变量初始化为值2.然后我们评估变量的值,然后决定是否应该执行 println 语句。

上面的代码的输出将是:

The value is less than 100

2、if / else语句

我们将看到的下一个决策语句是 if / else 语句。

这种说法的一般形式是:

if(condition) { 
   statement #1 
   statement #2 
   ... 
} else{ 
   statement #3 
   statement #4  
}

这个语句的一般工作是首先在 if 语句中评估一个条件。如果条件为真,则其后执行语句,并在else条件之前停止并退出循环。如果条件为假,则执行else语句块中的语句,然后退出循环。

下图显示了 if 语句的流程:

下面是一个if / else语句的例子:

class Example { 
   static void main(String[] args) { 
      // Initializing a local variable 
      int a = 2
		
      //Check for the boolean condition 
      if (a<100) { 
         //If the condition is true print the following statement 
         println("The value is less than 100"); 
      } else { 
         //If the condition is false print the following statement 
         println("The value is greater than 100"); 
      } 
   } 
}

在上面的例子中,我们首先将一个变量初始化为值2.然后我们评估变量的值,然后决定应该执行哪个 println 语句。

上面的代码的输出将是:

The value is less than 100.

3、嵌套if语句

有时需要有多个if语句嵌入在彼此内部。

这种说法的一般形式是:

if(condition) { 
   statement #1 
   statement #2 
   ... 
} else if(condition) { 
   statement #3 
   statement #4 
} else { 
   statement #5 
   statement #6 
}

以下是嵌套if / else语句的示例:

class Example { 
   static void main(String[] args) { 
      // Initializing a local variable 
      int a = 12 
		
      //Check for the boolean condition 
      if (a>100) {
         //If the condition is true print the following statement 
         println("The value is less than 100"); 
      } else 
         // Check if the value of a is greater than 5 
			
      if (a>5) { 
         //If the condition is true print the following statement 
         println("The value is greater than 5 and greater than 100"); 
      } else { 
         //If the condition is false print the following statement 
         println("The value of a is less than 5"); 
      }  
   } 
}	     

在上面的例子中,我们首先将一个变量初始化为值12.在第一个 if 语句中,我们看到 a 的值是否大于100。如果没有,那么我们进入第二个for循环,看看 a 的值是否大于5或小于5.上面的代码的输出将是:

The value is greater than 5 and greater than 100

4、​Switch语句

有时,嵌套的if-else语句是如此常见,并且经常使用,以便设计一个更容易的语句,称为 switch 语句。

switch(expression) { 
   case expression #1: 
   statement #1 
   ... 
   case expression #2: 
   statement #2 
   ... 
   case expression #N: 
   statement #N 
   ... 
   default:
   statement #Default 
   ... 
} 

本声明的一般工作如下:

  • 要评估的表达式放在switch语句中。

  • 将有多个case表达式被定义以基于表达式的计算来决定应该执行哪一组语句。

  • 在结尾处的语句的每个案例段中添加一个 break 语句。这是为了确保在执行相关语句集时立即退出循环。

  • 还有一个默认case 语句,如果没有任何前面的情况表达式求值为true,则执行。

下图显示了 switch-case 语句的流程:

以下是switch语句的示例:

class Example { 
   static void main(String[] args) { 
      //initializing a local variable 
      int a = 2
		
      //Evaluating the expression value 
      switch(a) {            
         //There is case statement defined for 4 cases 
         // Each case statement section has a break condition to exit the loop 
			
         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; 
      }
   }
}

在上面的例子中,我们首先将一个变量初始化为值2.然后我们有一个switch语句,它计算变量a的值。 基于变量的值,它将执行语句的相关案例集。

上面的代码的输出将是:

The value of a is Two

5、​嵌套switch语句  

它也可以有一个嵌套的 switch 语句。

语句的一般形式如下所示:

switch(expression) { 
   case expression #1: 
   statement #1 
   ... 
   case expression #2: 
   statement #2
   ... 
   case expression #N: 
   statement #N 
   ... 
   default: 
   statement #Default 
   ... 
}

下面是嵌套switch语句的一个示例:

class Example { 
   static void main(String[] args) { 
      //Initializing 2 variables i and j 
      int i = 0; 
      int j = 1; 
		
      // First evaluating the value of variable i 
      switch(i) { 
         case 0: 
            // Next evaluating the value of variable j 
            switch(j) { 
               case 0: 
                  println("i is 0, j is 0"); 
                  break; 
               case 1: 
                  println("i is 0, j is 1"); 
                  break; 
               
               // The default condition for the inner switch statement 
               default: 
               println("nested default case!!"); 
            } 
         break; 
			
         // The default condition for the outer switch statement 
         default: 
            println("No matching case found!!"); 
      }
   }
}

在上面的例子中,我们首先将a的变量初始化为a的值为2.然后我们有一个 switch 语句,它计算变量 a 的值。 基于变量的值,它将执行语句的相关案例集。

上面的代码的输出将是:

i is 0, j is 1

九、Groovy 方法

Groovy 中的方法是使用返回类型或使用 def 关键字定义的。方法可以接收任意数量的参数。定义参数时,不必显式定义类型。可以添加修饰符,如 public,private 和 protected。默认情况下,如果未提供可见性修饰符,则该方法为 public。

最简单的方法是没有参数的方法,如下所示:

def methodName() { 
   //Method code 
}

下面是一个简单方法的例子:

class Example {
   static def DisplayName() {
      println("This is how methods work in groovy");
      println("This is an example of a simple method");
   } 
	
   static void main(String[] args) {
      DisplayName();
   } 
}

在上面的例子中,DisplayName 是一个简单的方法,它由两个 println 语句组成,用于向控制台输出一些文本。在我们的静态 main 方法中,我们只是调用 DisplayName 方法。

上述方法的输出将是:

This is how methods work in groovy 
This is an example of a simple method

1、方法参数

如果一个方法的行为由一个或多个参数的值确定,则它通常是有用的。我们可以使用方法参数将值传递给被调用的方法。请注意,参数名称必须彼此不同。

使用参数的最简单的方法类型,如下所示:

def methodName(parameter1, parameter2, parameter3) { 
   // Method code goes here 
}

以下是使用参数的简单方法的示例:

class Example {
   static void sum(int a,int b) {
      int c = a+b;
      println(c);
   }  
	
   static void main(String[] args) {
      sum(10,5);
   } 
}

在这个例子中,我们创建一个带有 2 个参数 a 和 b 的 sum 方法。两个参数都是 int 类型。然后我们从我们的 main 方法中调用 sum 方法,并将值传递给变量 a 和 b。

然后我们从我们的 main 方法中调用 sum 方法,并将值传递给变量 a 和 b。

上述方法的输出将是值 15。

2、默认参数

Groovy 中还有一个规定来指定方法中的参数的默认值。 如果没有值传递给参数的方法,则使用缺省值。 如果使用非默认和默认参数,则必须注意,默认参数应在参数列表的末尾定义。

以下是使用参数的简单方法的示例:

def someMethod(parameter1, parameter2 = 0, parameter3 = 0) { 
   // Method code goes here 
} 

让我们看看我们之前看到的添加两个数字的相同示例,并创建一个具有一个默认和另一个非默认参数的方法。

class Example { 
   static void sum(int a,int b = 5) { 
      int c = a+b; 
      println(c); 
   } 
	
   static void main(String[] args) {
      sum(6); 
   } 
}

在这个例子中,我们创建一个具有两个参数 a 和 b 的 sum 方法。两个参数都是 int 类型。此示例和上一个示例的区别在于,在这种情况下,我们将 b 的默认值指定为5。

因此,当我们从 main 方法中调用 sum 方法时,我们可以选择只传递一个值为6的值,并将其分配给 sum 方法中的参数 a。

上述方法的输出将为值 11。

class Example {
   static void sum(int a,int b = 5) {
      int c = a+b;
      println(c);
   } 
	
   static void main(String[] args) {
      sum(6,6);
   } 
}

我们也可以通过传递 2 个值来调用 sum 方法,在上面的例子中,我们传递 2 个值 6 第二个值 6 实际上将替换分配给参数 b 的默认值。

上述方法的输出将是值 12。

3、方法返回值

方法也可以将值返回到调用程序。 这在现在编程语言中是必需的,其中方法执行某种计算,然后将所需值返回到调用方法。

下面是一个带有返回值的简单方法的例子:

class Example {
   static int sum(int a,int b = 5) {
      int c = a+b;
      return c;
   } 
	
   static void main(String[] args) {
      println(sum(6));
   } 
}

在我们上面的例子中,注意这次我们为我们的方法 sum 指定一个类型为 int 的返回类型。 在方法中,我们使用 return 语句将 sum 值发送到调用主程序。 由于方法的值现在可用于 main 方法,因此我们使用 println 函数在控制台中显示该值。

在前面的例子中,我们将我们的方法定义为静态方法,这意味着我们可以直接从类中访问这些方法。方法的下一个示例是实例方法,其中通过创建类的对象来访问方法。我们将在后面的章节中看到类,现在我们将演示如何使用方法。

上述方法的输出将为值 11。

4、实例方法

方法通常在 Groovy 中的类中实现,就像 Java 语言一样。类只是一个蓝图或模板,用于创建定义其属性和行为的不同对象。类对象显示由其类定义的属性和行为。因此,通过在类中创建方法来定义行为。

我们将在后面的章节中更详细地看到类,下面是类中方法实现的例子。

以下是如何实现方法的示例:

class Example { 
   int x; 
	
   public int getX() { 
      return x; 
   } 
	
   public void setX(int pX) { 
      x = pX; 
   } 
	
   static void main(String[] args) { 
      Example ex = new Example(); 
      ex.setX(100); 
      println(ex.getX()); 
   } 
}

在我们上面的例子中,这次我们没有为类方法指定静态属性。在我们的 main 函数中,我们实际上创建了一个 Example 类的实例,然后调用 'ex' 对象的方法。

上述方法的输出将是值 100。

5、本地和外部参数名称

Groovy 提供的设施就像java一样具有本地和全局参数。在下面的示例中,lx 是一个局部参数,它只具有 getX() 函数内的作用域,x 是一个全局属性,可以在整个 Example 类中访问。如果我们尝试访问 getX() 函数之外的变量 lx,我们将得到一个错误。

class Example { 
   static int x = 100; 
	
   public static int getX() { 
      int lx = 200; 
      println(lx); 
      return x; 
   } 
	
   static void main(String[] args) { 
      println getX() 
   }  
}

当我们运行上面的程序,我们会得到以下结果:

200 
100

6、方法属性

就像在 Java 中一样,groovy 可以使用 this 关键字访问它的实例成员。以下示例显示了当我们使用语句 this.x 时,它引用其实例并相应地设置x的值。

class Example { 
   int x = 100; 
	
   public int getX() { 
      this.x = 200; 
      return x; 
   } 
	
   static void main(String[] args) {
      Example ex = new Example(); 
      println(ex.getX());
   }
}

当我们运行上面的程序,我们将得到 200 的结果打印在控制台上。

十、Groovy 文件I/O

Groovy在使用I / O时提供了许多辅助方法,Groovy提供了更简单的类来为文件提供以下功能。

  • 读取文件
  • 写入文件
  • 遍历文件树
  • 读取和写入数据对象到文件

除此之外,您始终可以使用下面列出的用于文件I / O操作的标准Java类。

  • java.io.File
  • java.io.InputStream
  • java.io.OutputStream
  • java.io.Reader
  • java.io.Writer

1、读取文件

以下示例将输出Groovy中的文本文件的所有行。方法eachLine内置在Groovy中的File类中,目的是确保文本文件的每一行都被读取。

import java.io.File 
class Example { 
   static void main(String[] args) { 
      new File("E:/Example.txt").eachLine {  
         line -> println "line : $line"; 
      } 
   } 
}

File类用于实例化以文件名作为参数的新对象。 然后它接受eachLine的函数,将它放到一个line的变量并相应地打印它。

如果文件包含以下行,它们将被打印。

line : Example1
line : Example2

2、读取文件的内容到字符串

如果要将文件的整个内容作为字符串获取,可以使用文件类的text属性。

以下示例显示如何完成此操作:

class Example { 
   static void main(String[] args) { 
      File file = new File("E:/Example.txt") 
      println file.text 
   } 
}

如果该文件包含以下行,它们将被打印出来。

line : Example1 
line : Example2

3、写入文件

如果你想写入文件,你需要使用作家类输出文本到一个文件中。

下面的例子说明了如何可以做到这一点:

import java.io.File 
class Example { 
   static void main(String[] args) { 
      new File('E:/','Example.txt').withWriter('utf-8') { 
         writer -> writer.writeLine 'Hello World' 
      }  
   } 
}

如果你打开文件example.txt文件,您将看到文本中打印了“Hello World”这个词。

4、获取文件的大小

如果要获取文件的大小,可以使用文件类的length属性来获取,以下示例显示如何完成此操作。

class Example {
   static void main(String[] args) {
      File file = new File("E:/Example.txt")
      println "The file ${file.absolutePath} has ${file.length()} bytes"
   } 
}

上面的代码将显示文件的大小(以字节为单位)。

5、测试文件是否是目录

如果要查看路径是文件还是目录,可以使用File类的isFile和isDirectory选项。

以下示例显示如何完成此操作:

class Example { 
   static void main(String[] args) { 
      def file = new File('E:/') 
      println "File? ${file.isFile()}" 
      println "Directory? ${file.isDirectory()}" 
   } 
}

上面的代码将显示以下输出:

File? false 
Directory? True

6、创建目录

如果要创建一个新目录,可以使用File类的mkdir函数。

以下示例显示如何完成此操作:

class Example {
   static void main(String[] args) {
      def file = new File('E:/Directory')
      file.mkdir()
   } 
}

如果目录E:\ Directory不存在,将创建它。

7、删除文件

如果要删除文件,可以使用File类的delete功能。

以下示例显示如何完成此操作:

class Example {
   static void main(String[] args) {
      def file = new File('E:/Example.txt')
      file.delete()
   } 
}

如果存在该文件将被删除。

8、复制文件

Groovy还提供将内容从一个文件复制到另一个文件的功能。

以下示例显示如何完成此操作:

class Example {
   static void main(String[] args) {
      def src = new File("E:/Example.txt")
      def dst = new File("E:/Example1.txt")
      dst << src.text
   } 
}

将创建文件Example1.txt,并将文件Example.txt的所有内容复制到此文件。

9、获取目录内容

Groovy还提供了列出驱动器中的驱动器和文件的功能。

以下示例显示如何使用File类的listRoots函数显示机器上的驱动器。

class Example { 
   static void main(String[] args) { 
      def rootFiles = new File("test").listRoots() 
      rootFiles.each { 
         file -> println file.absolutePath 
      }
   }
}

根据机器上可用的驱动器,输出可能会有所不同。

在标准机器上的输出将类似于下面的一个:

C:\
D:\

以下示例显示如何使用File类的eachFile函数列出特定目录中的文件。

class Example {
   static void main(String[] args) {
      new File("E:/Temp").eachFile() {  
         file->println file.getAbsolutePath()
      }
   } 
}

输出将显示目录E:\ Temp中的所有文件。

如果要递归显示目录及其子目录中的所有文件,则可以使用File类的eachFileRecurse函数。以下示例显示如何完成此操作。

class Example { 
   static void main(String[] args) {
      new File("E:/temp").eachFileRecurse() {
         file -> println file.getAbsolutePath()
      }
   }
} 

输出将显示目录E:\ Temp中的所有文件及其子目录(如果存在)。

十一、Groovy 可选

Groovy是一个“可选”类型的语言,当理解语言的基本原理时,这种区别是一个重要的语言。与Java相比,Java是一种“强”类型的语言,由此编译器知道每个变量的所有类型,并且可以在编译时理解和尊重合同。这意味着方法调用能够在编译时确定。

当在Groovy中编写代码时,开发人员可以灵活地提供类型或不是类型。这可以提供一些简单的实现,并且当正确利用时,可以以强大和动态的方式为您的应用程序提供服务。

在Groovy中,可选的键入是通过'def'关键字完成的。

下面是一个使用def方法的例子:

class Example { 
   static void main(String[] args) { 
      // 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); 
   } 
} 

从上面的程序,我们可以看到,我们没有声明单个变量为Integer,float,double或string,即使它们包含这些类型的值。

当我们运行上面的程序,我们将得到以下结果:

100 
100.10 
100.101
HelloWorld

可选的打字在开发期间可以是一个强大的实用程序,但是当代码变得太大和复杂时,可能导致在后期开发阶段的可维护性问题。

要了解如何使用Groovy中的可选输入,而不让代码库陷入无法维护的混乱,最好在应用程序中采用“鸭式输入”的理念。

如果我们使用鸭式重写上面的代码,它将看起来像下面给出的。变量名称的名称比它们代表的类型更多,这使得代码更容易理解。

class Example { 
   static void main(String[] args) { 
      // Example of an Integer using def 
      def aint = 100; 
      println(aint); 
		
      // Example of an float using def 
      def bfloat = 100.10; 
      println(bfloat); 
		
      // Example of an Double using def 
      def cDouble = 100.101; 
      println(cDouble);
		
      // Example of an String using def 
      def dString = "HelloWorld"; 
      println(dString); 
   } 
}

十二、Groovy 数字

在 Groovy 中,数字实际上表示为对象,它们都是类 Integer 的一个实例。要使对象做某事,我们需要调用在其类中声明的一个方法。

Groovy 支持整数和浮点数。

  • 整数是不包含分数的值。
  • 浮点数是包含小数部分的十进制值。

Groovy 中的数字示例如下所示:

Integer x = 5; 
Float y = 1.25; 

其中 x 是整数类型,y 是浮点数。

Groovy 中的数字被定义为对象的原因通常是因为存在对数字执行操作的要求。在原始类型上提供类的概念被称为包装类。

默认情况下,Groovy 中提供了以下包装程序类。

包装类的对象包含或包装其各自的基本数据类型。将原始数据类型转换为对象的过程称为装箱,这由编译器负责。将对象转换回其对应的基本类型的过程称为取消装箱。

以下是装箱和拆箱的例子:

class Example { 
   static void main(String[] args) {
      Integer x = 5,y = 10,z = 0; 
		
      // The the values of 5,10 and 0 are boxed into Integer types 
      // The values of x and y are unboxed and the addition is performed 
      z = x+y; 
      println(z);
   }
}

上述程序的输出将为 15.在上述示例中,5,10 和 0 的值相应地首先嵌入到整数变量 x,y 和 z 中。上述程序的输出将是15。然后,当执行 x 和 y 的添加时,值从其整数类型取消装箱。

1、数字方法

由于 Groovy 中的 Numbers 表示为类,以下是可用的方法列表。

序号 方法和描述
1 ​xxxValue()​

此方法接受 Number 作为参数,并基于调用的方法返回基本类型。

2 ​compareTo()

compareTo 方法是使用比较一个数字与另一个数字。如果要比较数字的值,这是有用的。

3 ​equals()​

该方法确定调用方法的 Number 对象是否等于作为参数传递的对象。

4 ​valueOf()​

valueOf 方法返回保存所传递的参数的值的相关 Number 对象。

5 ​toString()​

该方法用于获取表示 Number 对象的值的 String 对象。

6

此方法用于获取某个 String 的原始数据类型。 parseXxx()是一个静态方法,可以有一个参数或两个参数。

7 ​abs()

该方法给出了参数的绝对值。参数可以是 int,float,long,double,short,byte。

8 ​ceil()​

方法 ceil 给出大于或等于参数的最小整数。

9 ​floor()

方法 floor 给出小于或等于参数的最大整数。

10 ​rint()​

方法 rint 返回值最接近参数的整数。

11 ​round()​

方法 round 返回最接近的 long 或 int,由方法返回类型给出。

12 ​min()

该方法给出两个参数中较小的一个。参数可以是 int,float,long,double。

13 ​max()​

该方法给出了两个参数的最大值。参数可以是 int,float,long,double。

14 ​exp()​

该方法返回自然对数e的底数为参数的幂。

15 ​log()

该方法返回参数的自然对数。

16 ​pow()​

该方法返回第一个参数的值增加到第二个参数的幂。

17 ​sqrt()​

该方法返回参数的平方根。

18 ​sin()​

该方法返回指定 double 值的正弦值。

19

​cos()
该方法返回指定 double 值的余弦值。

20

​tan()

该方法返回指定 double 值的正切值。

21

​asin()
该方法返回指定 double 值的反正弦值。

22

​acos()

该方法返回指定 double 值的反余弦值。

23

​atan()
该方法返回指定 double 值的反正切。

24 ​atan2()​

该方法将直角坐标(x,y)转换为极坐标(r,theta),并返回theta。

25

toDegrees()

该方法将参数值转换为度。

26 ​radian()​

该方法将参数值转换为弧度。

27

​random()

该方法用于生成介于0.0和1.0之间的随机数。范围是:0.0 = <Math.random <1.0。通过使用算术可以实现不同的范围。

十三、Groovy 字符串

reverse通过在引号中包含字符串文本,在Groovy中构造一个字符串文字。

Groovy提供了多种表示String字面量的方法。 Groovy中的字符串可以用单引号('),双引号(“)或三引号(”“”)括起来。此外,由三重引号括起来的Groovy字符串可以跨越多行。

以下是Groovy中字符串使用的示例 -

class Example { 
   static void main(String[] args) { 
      String a = 'Hello Single'; 
      String b = "Hello Double"; 
      String c = "'Hello Triple" + "Multiple lines'";
		
      println(a); 
      println(b); 
      println(c); 
   } 
}

当我们运行上面的程序,我们将得到以下结果 -

Hello Single 
Hello Double 
'Hello TripleMultiple lines'

1、字符串索引

Groovy中的字符串是字符的有序序列。字符串中的单个字符可以通过其位置访问。这由索引位置给出。

字符串索引从零开始,以小于字符串长度的一个结束。 Groovy还允许负索引从字符串的末尾开始计数。

以下是Groovy中字符串索引的使用示例 -

class Example { 
   static void main(String[] args) { 
      String sample = "Hello world"; 
      println(sample[4]); // Print the 5 character in the string
		
      //Print the 1st character in the string starting from the back 
      println(sample[-1]); 
      println(sample[1..2]);//Prints a string starting from Index 1 to 2 
      println(sample[4..2]);//Prints a string starting from Index 4 back to 2 
      
   } 
}

当我们运行上面的程序,我们将得到以下结果 -

o 
d 
el 
oll 

2、基本字符串操作

首先让我们学习groovy中的基本字符串操作。它们在下面给出。

序号 字符串操作和描述
1 ​Concatenation of two strings​

字符串的串联可以通过简单的'+'运算符来完成。

2 ​String Repetition

字符串的重复可以通过简单的'*'运算符完成。

3 ​String Length​

由字符串的length()方法确定的字符串的长度。

3、字符串方法

这里是String类支持的方法列表。

序号 方法和描述
1 ​center()

返回一个新的长度为numberOfChars的字符串,该字符串由左侧和右侧用空格字符填充的收件人组成。

2

​compareToIgnoreCase()             
按字母顺序比较两个字符串,忽略大小写差异。

3 ​concat()​

将指定的String连接到此String的结尾。

4 ​eachMatch()​

处理每个正则表达式组(参见下一节)匹配的给定String的子字符串。

5

​endsWith()             
测试此字符串是否以指定的后缀结尾。

6

​equalsIgnoreCase()             
将此字符串与另一个字符串进行比较,忽略大小写注意事项。

7

​getAt()             
它在索引位置返回字符串值。

8

​indexOf()             
返回此字符串中指定子字符串第一次出现的索引。

9

​matches()             
它输出字符串是否匹配给定的正则表达式。

10

​minus()             
删除字符串的值部分。

11

​next()             
此方法由++运算符为String类调用。它增加给定字符串中的最后一个字符。

12

​padLeft()             
填充字符串,并在左边附加空格。

13

​padRight()             
填充字符串,并在右边附加空格。

14

​plus()             
追加字符串

15

​previous()
此方法由CharSequence的 - 运算符调用。

16

​replaceAll()             
通过对该文本的关闭结果替换捕获的组的所有出现。

17

​reverse()             
创建一个与此String相反的新字符串。

18

​split()             
将此String拆分为给定正则表达式的匹配项。

19

​subString()             
返回一个新的String,它是此String的子字符串。

20

​toUpperCase()             
将此字符串中的所有字符转换为大写。

21

​toLowerCase()             
将此字符串中的所有字符转换为小写。

十四、Groovy 范围

范围是指定值序列的速记。范围由序列中的第一个和最后一个值表示,Range可以是包含或排除。包含范围包括从第一个到最后一个的所有值,而独占范围包括除最后一个之外的所有值。这里有一些范例文字的例子 -

  • 1..10 - 包含范围的示例
  • 1 .. <10 - 独占范围的示例
  • 'a'..'x' - 范围也可以由字符组成
  • 10..1 - 范围也可以按降序排列
  • 'x'..'a' - 范围也可以由字符组成并按降序排列。

以下是可用于范围的各种方法:

序号 方法和描述
1

​contains()             
检查范围是否包含特定值。

2

​get()             
返回此范围中指定位置处的元素。

3

​getFrom()             
获得此范围的下限值。

4

​getTo()             
获得此范围的上限值。

5

​isReverse()             
这是一个反向的范围,反向迭代

6 ​size()​

返回此范围的元素数。

7 ​subList()​

返回此指定的fromIndex(包括)和toIndex(排除)之间的此范围部分的视图。

十五、Groovy 列表

列表是用于存储数据项集合的结构。在 Groovy 中,List 保存了一系列对象引用。

List 中的对象引用占据序列中的位置,并通过整数索引来区分。

列表文字表示为一系列用逗号分隔并用方括号括起来的对象。

groovy 列表使用索引操作符 [] 索引。列表索引从 0 开始,指第一个元素。

groovy 中的一个列表中的数据可以是任意类型。这 java 下集合列表有些不同,java 下的列表是同种类型的数据集合。

groovy 列表可以嵌套列表。如 [1,2,[3,4,5],“aaa”] groovy 列表内置有反转方法 reverse()。调用 List.reverse() 可以实现列表反转。groovy 列表内置有排序方法 sort()。调用 List.sort() 可以实现列表排序。空列表表示为 [] 声明一个空集合:

def list1 = []  
def list2 = [1,2,3,4]  
list2.add(12)  
list2.add(12)  
println list1.size()

列表间的几个常用方法:

添加:

def list1 = [100, 101]
def list2 = [ 99,98,1]
println list2.plus(list1) //输出结果: [99, 98, 1, 100, 101]
// list2.plus(list1) 也可以写成 list2 + list1

删除:

def list1 = [12, 13]
def list2 = [11, 2, 33, 12, 13, 16]
println list2.minus(list1) //输出结果: [11, 2, 33, 16]
//list2.minus(list1) 也可以写成 list2 - list1

在本章中,我们将讨论 Groovy 中可用的列表方法。

序号 方法和描述
1

​add()             
将新值附加到此列表的末尾。

2

​contains()             
如果此列表包含指定的值,则返回 true。

3

​get()             
返回此列表中指定位置的元素。

4

​isEmpty()             
如果此列表不包含元素,则返回 true

5

​minus()             
创建一个由原始元素组成的新列表,而不是集合中指定的元素。

6

​plus()             
创建由原始元素和集合中指定的元素组成的新列表。

7

​pop()             
从此列表中删除最后一个项目。

8

​remove()             
删除此列表中指定位置的元素。

9

​reverse()             
创建与原始列表的元素相反的新列表。

10

​size()             
获取此列表中的元素数。

11

​sort()             
返回原始列表的排序副本。

十六、Groovy 映射

映射(也称为关联数组,字典,表和散列)是对象引用的无序集合。Map集合中的元素由键值访问。 Map中使用的键可以是任何类。当我们插入到Map集合中时,需要两个值:键和值。

以下是一些映射的例子 -

  • ['TopicName':'Lists','TopicName':'Maps'] - 具有TopicName作为键的键值对的集合及其相应的值。

  • [:] - 空映射。

Groovy中可用的映射方法:

序号 方法和描述
1

​containsKey()             
此映射是否包含此键?

2

​get()
查找此Map中的键并返回相应的值。如果此映射中没有键的条目,则返回null。

3

​keySet()             
获取此映射中的一组键。

4

​put()             
将指定的值与此映射中的指定键相关联。如果此映射先前包含此键的映射,则旧值将替换为指定的值。

5

​size()             
返回此映射中的键值映射的数量。

6

​values()             
返回此映射中包含的值的集合视图。

十七、Groovy 日期和时间

类Date表示特定的时刻,具有毫秒精度。 Date类有两个构造函数,如下所示。

1、Date()

句法:

public Date()

参数:

    无。

返回值:

分配一个Date对象并初始化它,以便它表示分配的时间,以最近的毫秒为单位。

下面是一个使用这个方法的例子:

class Example { 
   static void main(String[] args) { 
      Date date = new Date(); 
      
      // display time and date using toString() 
      System.out.println(date.toString()); 
   } 
} 

当我们运行上面的程序,我们将得到以下结果。以下输出将为您提供当前日期和时间 -

Thu Dec 10 21:31:15 GST 2015

2、Date (长毫秒)

句法:

public Date(long millisec)

参数:

毫秒 - millisecconds的数量,因为标准的基准时间指定。

返回值 -分配一个Date对象并将其初始化以表示自标准基准时间(称为“该历元”,即1970年1月1日,00:00:00 GMT)起指定的毫秒数。

下面是一个使用这个方法的例子:

class Example {
   static void main(String[] args) {
      Date date = new Date(100);
      
      // display time and date using toString()
      System.out.println(date.toString());
   } 
}

当我们运行上面的程序,我们将得到以下结果:

Thu Jan 01 04:00:00 GST 1970

以下是Date类的给定方法。在接受或返回年,月,日,小时,分钟和秒值的类Date的所有方法中,使用以下表示形式 -

  • 年y由整数y-1900表示。

  • 一个月份由0到11的整数表示; 0是1月,1是2月,等等;因此11是12月。

  • 日期(月中的日)以通常方式由1至31的整数表示。

  • 一个小时由从0到23的整数表示。因此,从午夜到上午1点的小时是小时0,而从中午到下午1点的小时是小时12。

  • 分钟由通常方式的0至59的整数表示。

  • 第二个由0至61的整数表示。

序号 方法和描述
1

​after()             
测试此日期是否在指定日期之后。

2

​equals()             
比较两个日期的相等性。当且仅当参数不为null时,结果为true,并且是表示与该对象时间相同的时间点(毫秒)的Date对象。

3

​compareTo()             
比较两个日期的顺序。

4

​toString()             
将此Date对象转换为字符串。

5

​before()             
测试此日期是否在指定日期之前。

6

​getTime()             
返回自此Date对象表示的1970年1月1日,00:00:00 GMT以来的毫秒数。

7

​setTime()             
设置此Date对象以表示一个时间点,即1970年1月1日00:00:00 GMT之后的时间毫秒。

十八、Groovy 正则表达式

正则表达式是用于在文本中查找子字符串的模式。 Groovy 使用〜“regex”表达式本地支持正则表达式。引号中包含的文本表示用于比较的表达式。

例如,我们可以创建一个正则表达式对象,如下所示 -

def regex = ~'Groovy'

当 Groovy 运算符=〜 if 和 while 语句(见第8章)中作为谓词(返回布尔值的表达式)出现时,左侧的 String 操作数与右侧的正则表达式操作数匹配。因此,以下每个都传递值 true

当定义正则表达式时,可以使用以下特殊字符

  • 有两个特殊的位置字符用于表示一行的开始和结束:caret(∧)和美元符号($)。

  • 正则表达式也可以包括量词。加号(+)表示一次或多次,应用于表达式的前一个元素。星号(*)用于表示零个或多个出现。问号(?)表示零或一次。

  • 元字符{和}用于匹配前一个字符的特定数量的实例。

  • 在正则表达式中,句点符号(。)可以表示任何字符。这被描述为通配符。

  • 正则表达式可以包括字符类。一组字符可以作为简单的字符序列,包含在元字符[和]中,如[aeiou]中。对于字母或数字范围,可以使用[a-z][a-mA-M]中的短划线分隔符。字符类的补码由方括号内的前导插入符号表示,如[∧a-z]中所示,并表示除指定的字符以外的所有字符。下面给出了正则表达式的一些示例。

'Groovy' =~ 'Groovy' 
'Groovy' =~ 'oo' 
'Groovy' ==~ 'Groovy' 
'Groovy' ==~ 'oo' 
'Groovy' =~ '∧G' 
'Groovy' =~ 'G$' 
'Groovy' =~ 'Gro*vy' 'Groovy' =~ 'Gro{2}vy'

十九、Groovy 异常处理

任何编程语言都需要异常处理来处理运行时错误,从而可以保持应用程序的正常流程。

异常通常会破坏应用程序的正常流程,这就是为什么我们需要在我们的应用程序中使用异常处理的原因。

例外大致分为以下类别:

  • 检测异常 -扩展Throwable类(除了RuntimeException和Error)的类称为检查异常egIOException,SQLException等。检查的异常在编译时检查。

一个典型的情况是FileNotFoundException。

假设您的应用程序中有以下代码,它从E盘中的文件读取。

class Example {
   static void main(String[] args) {
      File file = new File("E://file.txt");
      FileReader fr = new FileReader(file);
   } 
}

如果文件(file.txt)不在E盘中,那么将引发以下异常。

抓取:java.io.FileNotFoundException:E:\ file.txt(系统找不到指定的文件)。

java.io.FileNotFoundException:E:\ file.txt(系统找不到指定的文件)。

  • 未经检查的异常 -扩展RuntimeException的类称为未检查异常,例如,ArithmeticException,NullPointerException,ArrayIndexOutOfBoundsException等。未检查的异常在编译期不检查,而是在运行时检查。

一个典型的情况是ArrayIndexOutOfBoundsException,当您尝试访问大于数组长度的数组的索引时,会发生这种情况。以下是这种错误的典型例子。

class Example {
   static void main(String[] args) {
      def arr = new int[3];
      arr[5] = 5;
   } 
}

当上面的代码执行时,将引发以下异常。

抓取:java.lang.ArrayIndexOutOfBoundsException:5

java.lang.ArrayIndexOutOfBoundsException:5

  • 错误 -错误无法恢复。 OutOfMemoryError,VirtualMachineError,AssertionError等。

这些是程序永远不能恢复的错误,将导致程序崩溃。

下图显示了如何组织Groovy中的异常层次结构。它都基于Java中定义的层次结构。

1、捕捉异常

方法使用try和catch关键字的组合捕获异常。 try / catch块放置在可能生成异常的代码周围。

try { 
   //Protected code 
} catch(ExceptionName e1) {
   //Catch block 
}

所有可能引发异常的代码都放在受保护的代码块中。

在catch块中,您可以编写自定义代码来处理异常,以便应用程序可以从异常中恢复。

让我们看一个类似的代码示例,我们在上面看到一个索引值大于数组大小的数组。但这次让我们将我们的代码包装在try / catch块中。

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      } catch(Exception ex) {
         println("Catching the exception");
      }
		
      println("Let's move on after the exception");
   }
}

当我们运行上面的程序,我们将得到以下结果 -

Catching the exception 
Let's move on after the exception

从上面的代码,我们在try块中包装错误的代码。在catch块中,我们只是捕获我们的异常并输出一个异常已经发生的消息。

2、多个捕获块

可以有多个catch块来处理多种类型的异常。对于每个catch块,根据引发的异常的类型,您将编写代码来相应地处理它。

让我们修改上面的代码来具体捕捉ArrayIndexOutOfBoundsException。

以下是代码段:

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      }catch(ArrayIndexOutOfBoundsException ex) {
         println("Catching the Array out of Bounds exception");
      }catch(Exception ex) {
         println("Catching the exception");
      }
		
      println("Let's move on after the exception");
   } 
}

当我们运行上面的程序,我们将得到以下结果:

Catching the Aray out of Bounds exception 
Let's move on after the exception

从上面的代码,你可以看到ArrayIndexOutOfBoundsException catch块首先被捕获,因为它意味着异常的标准。

3、finally块

finally块跟在try块或catch块之后。代码的finally块总是执行,而不管异常的发生。

使用finally块可以运行任何你想要执行的清除类型语句,无论在受保护代码中发生什么。

该块的语法如下:

try { 
   //Protected code 
} catch(ExceptionType1 e1) { 
   //Catch block 
} catch(ExceptionType2 e2) { 
   //Catch block 
} catch(ExceptionType3 e3) { 
   //Catch block 
} finally {
   //The finally block always executes. 
}

让我们修改我们上面的代码并添加finally代码块。

以下是代码段:

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      } catch(ArrayIndexOutOfBoundsException ex) {
         println("Catching the Array out of Bounds exception");
      }catch(Exception ex) {
         println("Catching the exception");
      } finally {
         println("The final block");
      }
		
      println("Let's move on after the exception");
   } 
} 

当我们运行上面的程序,我们将得到以下结果:

Catching the Array out of Bounds exception 
The final block 
Let's move on after the exception

以下是Groovy中提供的异常方法:

  • public String getMessage()

返回有关已发生异常的详细消息。此消息在Throwable构造函数中初始化。

  • public Throwable getCause()

返回由Throwable对象表示的异常原因。

  • public String toString()

返回与getMessage()的结果连接的类的名称。

  • public void printStackTrace()

将toString()的结果与堆栈跟踪一起打印到System.err,错误输出流。

  • public StackTraceElement [] getStackTrace()

返回包含堆栈跟踪上的每个元素的数组。索引0处的元素表示调用堆栈的顶部,数组中的最后一个元素表示调用堆栈底部的方法。

  • public Throwable fillInStackTrace()

使用当前堆栈跟踪填充此Throwable对象的堆栈跟踪,添加到堆栈跟踪中的任何以前的信息。

下面是使用上面给出的一些方法的代码示例:

class Example {
   static void main(String[] args) {
      try {
         def arr = new int[3];
         arr[5] = 5;
      }catch(ArrayIndexOutOfBoundsException ex) {
         println(ex.toString());
         println(ex.getMessage());
         println(ex.getStackTrace());  
      } catch(Exception ex) {
         println("Catching the exception");
      }finally {
         println("The final block");
      }
		
      println("Let's move on after the exception");
   } 
}

当我们运行上面的程序,我们将得到以下结果:

java.lang.ArrayIndexOutOfBoundsException: 5 
5 
[org.codehaus.groovy.runtime.dgmimpl.arrays.IntegerArrayPutAtMetaMethod$MyPojoMetaMet 
hodSite.call(IntegerArrayPutAtMetaMethod.java:75), 
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) ,
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) ,
org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:133) ,
Example.main(Sample:8), sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method),
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57),
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ,
java.lang.reflect.Method.invoke(Method.java:606),
org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93),
groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325),
groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1443),
org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:893),
groovy.lang.GroovyShell.runScriptOrMainOrTestOrRunnable(GroovyShell.java:287),
groovy.lang.GroovyShell.run(GroovyShell.java:524),
groovy.lang.GroovyShell.run(GroovyShell.java:513),
groovy.ui.GroovyMain.processOnce(GroovyMain.java:652),
groovy.ui.GroovyMain.run(GroovyMain.java:384),
groovy.ui.GroovyMain.process(GroovyMain.java:370),
groovy.ui.GroovyMain.processArgs(GroovyMain.java:129),
groovy.ui.GroovyMain.main(GroovyMain.java:109),
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method),
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57),
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ,
java.lang.reflect.Method.invoke(Method.java:606),
org.codehaus.groovy.tools.GroovyStarter.rootLoader(GroovyStarter.java:109),
org.codehaus.groovy.tools.GroovyStarter.main(GroovyStarter.java:131),
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method),
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57),
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ,
java.lang.reflect.Method.invoke(Method.java:606),
com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)]
 
The final block 
Let's move on after the exception 

二十、Groovy 面向对象

在Groovy中,如在任何其他面向对象语言中一样,存在类和对象的概念以表示编程语言的对象定向性质。Groovy类是数据的集合和对该数据进行操作的方法。在一起,类的数据和方法用于表示问题域中的一些现实世界对象。

Groovy中的类声明了该类定义的对象的状态(数据)和行为。因此,Groovy类描述了该类的实例字段和方法。

以下是Groovy中的一个类的示例。类的名称是Student,它有两个字段 - StudentIDStudentName。在main函数中,我们创建一个这个类的对象,并将值分配给对象的StudentIDStudentName

class Student {
   int StudentID;
   String StudentName;
	
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
      st.StudentName = "Joe"     
   } 
}

1、getter和setter方法

在任何编程语言中,总是使用private关键字隐藏实例成员,而是提供getter和setter方法来相应地设置和获取实例变量的值。

以下示例显示如何完成此操作:

class Student {
   private int StudentID;
   private String StudentName;
	
   void setStudentID(int pID) {
      StudentID = pID;
   }
	
   void setStudentName(String pName) {
      StudentName = pName;
   }
	
   int getStudentID() {
      return this.StudentID;
   }
	
   String getStudentName() {
      return this.StudentName;
   }
	
   static void main(String[] args) {
      Student st = new Student();
      st.setStudentID(1);
      st.setStudentName("Joe");
		
      println(st.getStudentID());
      println(st.getStudentName());
   } 
}

当我们运行上面的程序,我们将得到以下结果:

1 
Joe 

请注意以下关于上述程序的要点:

  • 在类中,studentID和studentName都标记为private,这意味着无法从类外部访问它们。

  • 每个实例成员都有自己的getter和setter方法。getter方法返回实例变量的值,例如方法int getStudentID()和setter方法设置实例ID的值,例如method - void setStudentName(String pName)

2、实例方法

在类中包含更多的方法通常是一个很自然的事情,它实际上为类实现了一些功能。在我们的学生示例中,让我们添加Marks1,Marks2和Marks3的实例成员,以表示学生在3个科目中的标记。然后我们将添加一个新的实例方法,计算学生的总分。以下是代码的外观。

在下面的示例中,Total方法是一个额外的Instance方法,它内置了一些逻辑。

class Student {
   int StudentID;
   String StudentName;
	
   int Marks1;
   int Marks2;
   int Marks3;
	
   int Total() {
      return Marks1+Marks2+Marks3;
   }
	
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
      st.StudentName="Joe";
		
      st.Marks1 = 10;
      st.Marks2 = 20;
      st.Marks3 = 30;
		
      println(st.Total());
   }
}

当我们运行上面的程序,我们将得到以下结果:

60

3、创建多个对象

你也可以创建一个类的多个对象。下面是如何实现这一点的例子。在这里,我们创建3个对象(st,st1和st2)并相应地调用它们的实例成员和实例方法。

class Student {
   int StudentID;
   String StudentName;
	
   int Marks1;
   int Marks2;
   int Marks3;
	
   int Total() { 
      return Marks1+Marks2+Marks3;
   } 
	
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
      st.StudentName = "Joe";
		
      st.Marks1 = 10;
      st.Marks2 = 20;
      st.Marks3 = 30;
		
      println(st.Total()); 
   
      Student st1 = new Student();
      st1.StudentID = 1;
      st1.StudentName = "Joe";
		
      st1.Marks1 = 10;
      st1.Marks2 = 20;
      st1.Marks3 = 40;
		
      println(st1.Total());  
        
      Student st2 = new Student();
      st2.StudentID = 1;
      st2.StudentName = "Joe";
		
      st2.Marks1 = 10; 
      st2.Marks2 = 20;
      st2.Marks3 = 50;
		
      println(st2.Total());
   } 
} 

当我们运行上面的程序,我们将得到以下结果:

60 
70 
80 

4、继承

继承可以定义为一个类获取另一个类的属性(方法和字段)的过程。通过使用继承,信息以分级顺序可管理。

继承其他属性的类称为子类(派生类,子类),属性继承的类称为超类(基类,父类)。

5、扩展

extends是用于继承类的属性的关键字。下面给出了extends关键字的语法。在下面的例子中,我们做了以下事情 -

  • 创建一个名为Person的类。这个类有一个名为name的实例成员。

  • 创建一个名为Student的类,它从Person类继承。请注意,在Person类中定义的名称实例成员在Student类中继承。

  • 在Student类构造函数中,我们调用了基类构造函数。

  • 在我们的Student类中,我们添加了2个StudentID和Marks1的实例成员。

class Example {
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
		
      st.Marks1 = 10;
      st.name = "Joe";
		
      println(st.name);
   }
} 

class Person {
   public String name;
   public Person() {}  
} 

class Student extends Person {
   int StudentID
   int Marks1;
	
   public Student() {
      super();
   } 
}   

当我们运行上面的程序,我们将得到以下结果 -

Joe

6、内部类

内部类在另一个类中定义。封闭类可以像往常一样使用内部类。另一方面,内部类可以访问其封闭类的成员,即使它们是私有的。不允许除封闭类之外的类访问内部类。

下面是一个外部和内部类的例子。在下面的例子中,我们做了以下事情:

  • 创建一个名为Outer的类,它将是我们的外部类。
  • 在Outer类中定义名为name的字符串。
  • 在我们的外类中创建一个内部或嵌套类。
  • 请注意,在内部类中,我们可以访问在Outer类中定义的名称实例成员。
class Example { 
   static void main(String[] args) { 
      Outer outobj = new Outer(); 
      outobj.name = "Joe"; 
      outobj.callInnerMethod() 
   } 
} 

class Outer { 
   String name;
	
   def callInnerMethod() { 
      new Inner().methodA() 
   } 
	
   class Inner {
      def methodA() { 
         println(name); 
      } 
   } 
	
}   

当我们运行上面的程序,我们将得到以下结果:

Joe

7、抽象类

抽象类表示通用概念,因此,它们不能被实例化,被创建为子类化。他们的成员包括字段/属性和抽象或具体方法。抽象方法没有实现,必须通过具体子类来实现。抽象类必须用抽象关键字声明。抽象方法也必须用抽象关键字声明。

在下面的示例中,请注意,Person类现在是一个抽象类,不能被实例化。还要注意,在抽象类中有一个名为DisplayMarks的抽象方法,没有实现细节。

在学生类中,必须添加实现细节:

class Example { 
   static void main(String[] args) { 
      Student st = new Student(); 
      st.StudentID = 1;
		
      st.Marks1 = 10; 
      st.name="Joe"; 
		
      println(st.name); 
      println(st.DisplayMarks()); 
   } 
} 

abstract class Person { 
   public String name; 
   public Person() { } 
   abstract void DisplayMarks();
}
 
class Student extends Person { 
   int StudentID 
   int Marks1; 
	
   public Student() { 
      super(); 
   } 
	
   void DisplayMarks() { 
      println(Marks1); 
   }  
} 

当我们运行上面的程序,我们将得到以下结果 -

Joe 
10 

8、接口

接口定义了类需要遵守的契约。接口仅定义需要实现的方法的列表,但是不定义方法实现。需要使用interface关键字声明接口。接口仅定义方法签名。接口的方法总是公开的。在接口中使用受保护或私有方法是一个错误。

以下是groovy中的接口示例。在下面的例子中,我们做了以下事情:

  • 创建一个名为Marks的接口并创建一个名为DisplayMarks的接口方法。

  • 在类定义中,我们使用implements关键字来实现接口。 因为我们是实现

  • 因为我们正在实现接口,我们必须为DisplayMarks方法提供实现。

class Example {
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
      st.Marks1 = 10;
      println(st.DisplayMarks());
   } 
} 

interface Marks { 
   void DisplayMarks(); 
} 

class Student implements Marks {
   int StudentID
   int Marks1;
	
   void DisplayMarks() {
      println(Marks1);
   }
}

当我们运行上面的程序,我们将得到以下结果 -

10

二十一、Groovy 泛型

在定义类,接口和方法时,泛型使能类型(类和接口)作为参数。与在方法声明中使用的更熟悉的形式参数非常类似,类型参数提供了一种方法,可以为不同的输入重复使用相同的代码。区别在于形式参数的输入是值,而类型参数的输入是类型。

1、集合的通用

可以对集合类(如List类)进行一般化,以便只有该类型的集合在应用程序中被接受。下面显示了一般化ArrayList的示例。以下语句的作用是它只接受类型为string的列表项 -

List<String> list = new ArrayList<String>();

在下面的代码示例中,我们将执行以下操作:

  • 创建一个只包含字符串的通用ArrayList集合。
  • 向列表中添加3个字符串。
  • 对于列表中的每个项目,打印字符串的值。
class Example {
   static void main(String[] args) {
      // Creating a generic List collection
      List<String> list = new ArrayList<String>();
      list.add("First String");
      list.add("Second String");
      list.add("Third String");
		
      for(String str : list) {
         println(str);
      }
   } 
}

上述程序的输出将是:

First String 
Second String 
Third String

2、泛型类

整个类也可以泛化。这使得类更灵活地接受任何类型,并相应地与这些类型工作。让我们来看一个例子,说明我们如何做到这一点。

在以下程序中,我们执行以下步骤:

  • 我们正在创建一个名为ListType的类。注意放置在类定义前面的<T>关键字。这告诉编译器这个类可以接受任何类型。因此,当我们声明这个类的一个对象时,我们可以在声明期间指定一个类型,并且该类型将在占位符<T>。

  • 泛型类有简单的getter和setter方法来处理类中定义的成员变量。

  • 在主程序中,注意我们能够声明ListType类的对象,但是不同类型的对象。第一个类型是Integer类型,第二个类型是String类型。

class Example {
   static void main(String[] args) {
      // Creating a generic List collection 
      ListType<String> lststr = new ListType<>();
      lststr.set("First String");
      println(lststr.get()); 
		
      ListType<Integer> lstint = new ListType<>();
      lstint.set(1);
      println(lstint.get());
   }
} 

public class ListType<T> {
   private T localt;
	
   public T get() {
      return this.localt;
   }
	
   public void set(T plocal) {
      this.localt = plocal;
   } 
}

上述程序的输出将是:

First String 
1

二十二、Groovy 特征

特征是语言的结构构造,允许 -

  • 行为的组成。
  • 接口的运行时实现。
  • 与静态类型检查/编译的兼容性

它们可以被看作是承载默认实现和状态的接口。使用trait关键字定义 trait。

下面给出了一个特征的例子:

trait Marks {
   void DisplayMarks() {
      println("Display Marks");
   } 
}

然后可以使用 implement 关键字以类似于接口的方式实现 trait。

class Example {
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
      st.Marks1 = 10; 
      println(st.DisplayMarks());
   } 
} 

trait Marks { 
   void DisplayMarks() {
      println("Display Marks");
   } 
} 

class Student implements Marks { 
   int StudentID
   int Marks1;
}

实现接口

Traits 可以实现接口,在这种情况下,使用 interface 关键字声明接口。

下面给出了实现接口的特征的示例。在以下示例中,可以注意以下要点。

  • 接口 Total 使用方法 DisplayTotal 定义。

  • 特征 Marks 实现了 Total 接口,因此需要为 DisplayTotal 方法提供一个实现。

class Example {
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
      st.Marks1 = 10;
		
      println(st.DisplayMarks());
      println(st.DisplayTotal());
   } 
} 

interface Total {
   void DisplayTotal() 
} 

trait Marks implements Total {
   void DisplayMarks() {
      println("Display Marks");
   }
	
   void DisplayTotal() {
      println("Display Total"); 
   } 
} 

class Student implements Marks { 
   int StudentID
   int Marks1;  
} 

上述程序的输出将是:

Display Marks 
Display Total

1、属性

特征可以定义属性。下面给出了具有属性的trait的示例。

在以下示例中,integer 类型的 Marks1 是一个属性。

class Example {
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
		
      println(st.DisplayMarks());
      println(st.DisplayTotal());
   } 
	
   interface Total {
      void DisplayTotal() 
   } 
	
   trait Marks implements Total {
      int Marks1;
		
      void DisplayMarks() {
         this.Marks1 = 10;
         println(this.Marks1);
      }
		
      void DisplayTotal() {
         println("Display Total");
      } 
   } 
	
   class Student implements Marks {
      int StudentID 
   }
} 

上述程序的输出将是:

10 
Display Total

2、行为的构成

特征可以用于以受控的方式实现多重继承,避免钻石问题。在下面的代码示例中,我们定义了两个特征 - Marks 和 Total。我们的 Student 类实现了两个特征。由于学生类扩展了这两个特征,它能够访问这两种方法 - DisplayMarks 和 DisplayTotal。

class Example {
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
		
      println(st.DisplayMarks());
      println(st.DisplayTotal()); 
   } 
} 

trait Marks {
   void DisplayMarks() {
      println("Marks1");
   } 
} 

trait Total {
   void DisplayTotal() { 
      println("Total");
   } 
}  

class Student implements Marks,Total {
   int StudentID 
}   

上述程序的输出将是:

Marks1
Total 

3、扩展特征

特征可能扩展另一个特征,在这种情况下,必须使用extends关键字。

在下面的代码示例中,我们使用 Marks trait 扩展了 Total trait:

class Example {
   static void main(String[] args) {
      Student st = new Student();
      st.StudentID = 1;
      println(st.DisplayMarks());
   } 
} 

trait Marks {
   void DisplayMarks() {
      println("Marks1");
   } 
} 

trait Total extends Marks {
   void DisplayMarks() {
      println("Total");
   } 
}  

class Student implements Total {
   int StudentID 
}

上述程序的输出将是:

Total

二十三、Groovy 闭包

闭包是一个短的匿名代码块。它通常跨越几行代码。一个方法甚至可以将代码块作为参数。它们是匿名的。

下面是一个简单闭包的例子,它是什么样子。

class Example {
   static void main(String[] args) {
      def clos = {println "Hello World"};
      clos.call();
   } 
}

在上面的例子中,代码行 - {println“Hello World”}被称为闭包。此标识符引用的代码块可以使用call语句执行。

当我们运行上面的程序,我们将得到以下结果 :

Hello World

1、闭包中的形式参数

闭包也可以包含形式参数,以使它们更有用,就像Groovy中的方法一样。

class Example {
   static void main(String[] args) {
      def clos = {param->println "Hello ${param}"};
      clos.call("World");
   } 
}

在上面的代码示例中,注意使用$ {param},这导致closure接受一个参数。当通过clos.call语句调用闭包时,我们现在可以选择将一个参数传递给闭包。

当我们运行上面的程序,我们将得到以下结果:

Hello World

下一个图重复了前面的例子并产生相同的结果,但显示可以使用被称为它的隐式单个参数。这里的'it'是Groovy中的关键字。

class Example {
   static void main(String[] args) {
      def clos = {println "Hello ${it}"};
      clos.call("World");
   } 
}

当我们运行上面的程序,我们将得到以下结果:

Hello World

2、闭包和变量

更正式地,闭包可以在定义闭包时引用变量。

以下是如何实现这一点的示例:

class Example {     
   static void main(String[] args) {
      def str1 = "Hello";
      def clos = {param -> println "${str1} ${param}"}
      clos.call("World");
		
      // We are now changing the value of the String str1 which is referenced in the closure
      str1 = "Welcome";
      clos.call("World");
   } 
}

在上面的例子中,除了向闭包传递参数之外,我们还定义了一个名为str1的变量。闭包也接受变量和参数。

当我们运行上面的程序,我们将得到以下结果:

Hello World 
Welcome World

3、在方法中使用闭包

闭包也可以用作方法的参数。在Groovy中,很多用于数据类型(例如列表和集合)的内置方法都有闭包作为参数类型。

以下示例显示如何将闭包作为参数发送到方法:

class Example { 
   def static Display(clo) {
      // This time the $param parameter gets replaced by the string "Inner"         
      clo.call("Inner");
   } 
	
   static void main(String[] args) {
      def str1 = "Hello";
      def clos = { param -> println "${str1} ${param}" }
      clos.call("World");
		
      // We are now changing the value of the String str1 which is referenced in the closure
      str1 = "Welcome";
      clos.call("World");
		
      // Passing our closure to a method
      Example.Display(clos);
   } 
}

在上述示例中:

  • 我们定义一个名为Display的静态方法,它将闭包作为参数。

  • 然后我们在我们的main方法中定义一个闭包,并将它作为一个参数传递给我们的Display方法。

当我们运行上面的程序,我们将得到以下结果:

Hello World 
Welcome World 
Welcome Inner

4、集合和字符串中的闭包

几个List,Map和String方法接受一个闭包作为参数。让我们看看在这些数据类型中如何使用闭包的例子。

1)使用闭包和列表

以下示例显示如何使用闭包与列表。在下面的例子中,我们首先定义一个简单的值列表。列表集合类型然后定义一个名为.each的函数。此函数将闭包作为参数,并将闭包应用于列表的每个元素

class Example {
   static void main(String[] args) {
      def lst = [11, 12, 13, 14];
      lst.each {println it}
   } 
}

当我们运行上面的程序,我们将得到以下结果:

11 
12 
13 
14

2)使用映射闭包

以下示例显示了如何使用闭包。在下面的例子中,我们首先定义一个简单的关键值项Map。然后,映射集合类型定义一个名为.each的函数。此函数将闭包作为参数,并将闭包应用于映射的每个键值对。

class Example {
   static void main(String[] args) {
      def mp = ["TopicName" : "Maps", "TopicDescription" : "Methods in Maps"]             
      mp.each {println it}
      mp.each {println "${it.key} maps to: ${it.value}"}
   } 
}

当我们运行上面的程序,我们会得到以下结果:

TopicName = Maps 
TopicDescription = Methods in Maps 
TopicName maps to: Maps 
TopicDescription maps to: Methods in Maps

通常,我们可能希望遍历集合的成员,并且仅当元素满足一些标准时应用一些逻辑。这很容易用闭包中的条件语句来处理。

class Example {
   static void main(String[] args) {
      def lst = [1,2,3,4];
      lst.each {println it}
      println("The list will only display those numbers which are divisible by 2")
      lst.each{num -> if(num % 2 == 0) println num}
   } 
}

上面的例子显示了在闭包中使用的条件if(num%2 == 0)表达式,用于检查列表中的每个项目是否可被2整除。

当我们运行上面的程序,我们会得到以下结果:

1 
2 
3 
4 
The list will only display those numbers which are divisible by 2.
2 
4 

5、闭包使用的方法

闭包本身提供了一些方法:

序号 方法和描述
1

​find()             
find方法查找集合中与某个条件匹配的第一个值。

2

​findAll()             
它找到接收对象中与闭合条件匹配的所有值。

3

​any() & every()             
方法any迭代集合的每个元素,检查布尔谓词是否对至少一个元素有效。

4

​collect()             
该方法通过集合收集迭代,使用闭包作为变换器将每个元素转换为新值。

二十四、Groovy 注释

操作没有直接影响。

注释主要用于以下原因:

  • 编译器信息 -编译器可以使用注释来检测错误或抑制警告。

  • 编译时和部署时处理 -软件工具可以处理注释信息以生成代码,XML文件等。

  • 运行时处理 -一些注释可以在运行时检查。

在Groovy中,基本注释如下所示:

@interface - at符号字符(@)向编译器指示以下是注释。

注释可以以没有主体的方法的形式和可选的默认值来定义成员。

注释可以应用于以下类型:

1、单行注释 

单行注释以//开头,并且能在行的任何位置。从//开始,到一行结束,都被认为是注释的部分。

// a standalone single line comment
println "hello" // a comment till the end of the line

2、多行注释 

多行注释以/*开头,并且能在行的任何位置 。以/*开头,包括新的行,直到第一个*/结束都被认为是注释的部分。多行注释可以放于声明的开始或者声明的中间。

/* a standalone multiline comment
   spanning two lines */
println "hello" /* a multiline comment starting
                   at the end of a statement */
println 1 /* one */ + 2 /* two */

3、字符串类型

下面给出了字符串注释的一个例子:

@interface Simple { 
   String str1() default "HelloWorld"; 
}

4、枚举类型

enum DayOfWeek { mon, tue, wed, thu, fri, sat, sun } 
@interface Scheduled {
   DayOfWeek dayOfWeek() 
} 

5、类类型

@interface Simple {} 
@Simple 
class User {
   String username
   int age
}
 
def user = new User(username: "Joe",age:1); 
println(user.age); 
println(user.username);

6、注释成员值

使用注释时,需要至少设置所有没有默认值的成员。下面给出一个例子。当定义后使用注释示例时,需要为其分配一个值。

@interface Example {
   int status() 
}

@Example(status = 1)

7、关闭注释参数

Groovy中注释的一个很好的特性是,你也可以使用闭包作为注释值。因此,注释可以与各种各样的表达式一起使用。

下面给出一个例子。注释Onlyif是基于类值创建的。然后注释应用于两个方法,它们基于数字变量的值向结果变量发布不同的消息。

@interface OnlyIf {
   Class value() 
}  

@OnlyIf({ number<=6 }) 
void Version6() {
   result << 'Number greater than 6' 
} 

@OnlyIf({ number>=6 }) 
void Version7() {
   result << 'Number greater than 6' 
}

8、元注释

这是groovy中注释的一个非常有用的功能。有时可能有一个方法的多个注释,如下所示。

有时这可能变得麻烦有多个注释:

@Procedure 
@Master class 
MyMasterProcedure {} 

在这种情况下,您可以定义一个元注释,它将多个注释集中在一起,并将元注释应用于该方法。所以对于上面的例子,你可以使用AnnotationCollector来定义注释的集合。

import groovy.transform.AnnotationCollector
  
@Procedure 
@Master 
@AnnotationCollector

一旦完成,您可以应用以下元注释器到该方法:

import groovy.transform.AnnotationCollector
  
@Procedure 
@Master 
@AnnotationCollector
  
@MasterProcedure 
class MyMasterProcedure {}

二十五、Groovy XML

XML是一种便携的开放源代码语言,允许程序员开发可以被其他应用程序读取的应用程序,而不管操作系统和/或开发语言。这是用于在应用程序之间交换数据的最常用的语言之一。

1、XML 简介

可扩展标记语言XML是一种非常类似于HTML或SGML的标记语言。这是万维网联盟推荐的,可作为开放标准。XML对于跟踪少量到中等数据量而不需要基于SQL的骨干非常有用。

2、Groovy中的XML支持

Groovy语言还提供了对XML语言的丰富支持。使用的两个最基本的XML类是:

  • XML标记构建器 - Groovy支持基于树的标记生成器BuilderSupport,它可以被子类化以生成各种树结构对象表示。通常,这些构建器用于表示XML标记,HTML标记。 Groovy的标记生成器捕获对伪方法的调用,并将它们转换为树结构的元素或节点。这些伪方法的参数被视为节点的属性。作为方法调用一部分的闭包被视为生成的树节点的嵌套子内容。

  • XML解析器 - Groovy XmlParser类使用一个简单的模型来将XML文档解析为Node实例的树。每个节点都有XML元素的名称,元素的属性和对任何子节点的引用。这个模型足够用于大多数简单的XML处理。

对于所有的XML代码示例,让我们使用以下简单的XML文件movies.xml来构建XML文件并随后读取该文件。

<collection shelf = "New Arrivals"> 

   <movie title = "Enemy Behind"> 
      <type>War, Thriller</type> 
      <format>DVD</format> 
      <year>2003</year> 
      <rating>PG</rating> 
      <stars>10</stars> 
      <description>Talk about a US-Japan war</description> 
   </movie> 
	
   <movie title = "Transformers"> 
      <type>Anime, Science Fiction</type>
      <format>DVD</format> 
      <year>1989</year> 
      <rating>R</rating> 
      <stars>8</stars> 
      <description>A schientific fiction</description> 
   </movie> 
	
   <movie title = "Trigun"> 
      <type>Anime, Action</type> 
      <format>DVD</format> 
      <year>1986</year> 
      <rating>PG</rating> 
      <stars>10</stars> 
      <description>Vash the Stam pede!</description> 
   </movie> 
	
   <movie title = "Ishtar"> 
      <type>Comedy</type> 
      <format>VHS</format> 
      <year>1987</year> 
      <rating>PG</rating> 
      <stars>2</stars> 
      <description>Viewable boredom </description> 
   </movie> 
	
</collection> 

3、XML标记生成器

句法:

public MarkupBuilder()

MarkupBuilder用于构造整个XML文档。通过首先创建XML文档类的对象来创建XML文档。一旦创建了对象,可以调用伪方法来创建XML文档的各种元素。

让我们来看一个如何创建一个块的示例,即从上述XML文档中创建一个电影元素:

import groovy.xml.MarkupBuilder 

class Example {
   static void main(String[] args) {
      def mB = new MarkupBuilder()
		
      // Compose the builder
      mB.collection(shelf : 'New Arrivals') {
         movie(title : 'Enemy Behind')
         type('War, Thriller')
         format('DVD')
         year('2003')
         rating('PG')
         stars(10)
         description('Talk about a US-Japan war') 
      }
   } 
}

在上面的例子中,需要注意以下几点:

  • mB.collection() -这是一个标记生成器,用于创建<collection> </ collection>的头XML标签

  • movie(title : 'Enemy Behind') -这些伪方法使用此方法创建带有值的标记的子标记。通过指定一个名为title的值,这实际上表示需要为该元素创建一个属性。

  • 向伪方法提供闭包以创建XML文档的剩余元素。

  • 初始化类MarkupBuilder的默认构造函数,以便将生成的XML发布到标准输出流

当我们运行上面的程序,我们将得到以下结果:

<collection shelf = 'New Arrivals'> 
   <movie title = 'Enemy Behind' /> 
      <type>War, Thriller</type> 
      <format>DVD</format> 
      <year>2003</year> 
      <rating>PG</rating> 
      <stars>10</stars> 
      <description>Talk about a US-Japan war</description> 
   </movie> 
</collection>

为了创建整个XML文档,需要执行以下操作。

  • 需要创建映射条目以存储元素的不同值。
  • 对于地图的每个元素,我们将值分配给每个元素。
import groovy.xml.MarkupBuilder 

class Example {
   static void main(String[] args) {
      def mp = [1 : ['Enemy Behind', 'War, Thriller','DVD','2003', 
         'PG', '10','Talk about a US-Japan war'],
         2 : ['Transformers','Anime, Science Fiction','DVD','1989', 
         'R', '8','A scientific fiction'],
         3 : ['Trigun','Anime, Action','DVD','1986', 
         'PG', '10','Vash the Stam pede'],
         4 : ['Ishtar','Comedy','VHS','1987', 'PG', 
         '2','Viewable boredom ']] 
			
      def mB = new MarkupBuilder()  
		
      // Compose the builder
      def MOVIEDB = mB.collection('shelf': 'New Arrivals') {
         mp.each {
            sd -> 
            mB.movie('title': sd.value[0]) {  
               type(sd.value[1])
               format(sd.value[2])
               year(sd.value[3]) 
               rating(sd.value[4])
               stars(sd.value[4]) 
               description(sd.value[5]) 
            }
         }
      }
   } 
} 

当我们运行上面的程序,我们将得到以下结果:

<collection shelf = 'New Arrivals'> 
   <movie title = 'Enemy Behind'> 
      <type>War, Thriller</type> 
      <format>DVD</format> 
      <year>2003</year> 
      <rating>PG</rating> 
      <stars>PG</stars> 
      <description>10</description> 
   </movie> 
   <movie title = 'Transformers'> 
      <type>Anime, Science Fiction</type> 
      <format>DVD</format> 
      <year>1989</year>
	  <rating>R</rating> 
      <stars>R</stars> 
      <description>8</description> 
   </movie> 
   <movie title = 'Trigun'> 
      <type>Anime, Action</type> 
      <format>DVD</format> 
      <year>1986</year> 
      <rating>PG</rating> 
      <stars>PG</stars> 
      <description>10</description> 
   </movie> 
   <movie title = 'Ishtar'> 
      <type>Comedy</type> 
      <format>VHS</format> 
      <year>1987</year> 
      <rating>PG</rating> 
      <stars>PG</stars> 
      <description>2</description> 
   </movie> 
</collection> 

4、XML解析

Groovy XmlParser类使用一个简单的模型来将XML文档解析为Node实例的树。每个节点都有XML元素的名称,元素的属性和对任何子节点的引用。这个模型足够用于大多数简单的XML处理。

句法:

public XmlParser() 
   throws ParserConfigurationException, 
      SAXException

以下代码显示了如何使用XML解析器读取XML文档的示例。

让我们假设我们有同样的文档,名为Movies.xml,我们想解析XML文档并向用户显示一个正确的输出。以下代码是我们如何遍历XML文档的整个内容并向用户显示正确响应的代码段。

import groovy.xml.MarkupBuilder 
import groovy.util.*

class Example {

   static void main(String[] args) { 
	
      def parser = new XmlParser()
      def doc = parser.parse("D:Movies.xml");
		
      doc.movie.each{
         bk->
         print("Movie Name:")
         println "${bk['@title']}"
			
         print("Movie Type:")
         println "${bk.type[0].text()}"
			
         print("Movie Format:")
         println "${bk.format[0].text()}"
			
         print("Movie year:")
         println "${bk.year[0].text()}"
			
         print("Movie rating:")
         println "${bk.rating[0].text()}"
			
         print("Movie stars:")
         println "${bk.stars[0].text()}"
			
         print("Movie description:")
         println "${bk.description[0].text()}"
         println("*******************************")
      }
   }
} 

当我们运行上面的程序,我们将得到以下结果:

Movie Name:Enemy Behind 
Movie Type:War, Thriller 
Movie Format:DVD 
Movie year:2003 
Movie rating:PG 
Movie stars:10 
Movie description:Talk about a US-Japan war 
******************************* 
Movie Name:Transformers 
Movie Type:Anime, Science Fiction 
Movie Format:DVD 
Movie year:1989 
Movie rating:R 
Movie stars:8 
Movie description:A schientific fiction 
******************************* 
Movie Name:Trigun 
Movie Type:Anime, Action
Movie Format:DVD 
Movie year:1986 
Movie rating:PG 
Movie stars:10 
Movie description:Vash the Stam pede! 
******************************* 
Movie Name:Ishtar 
Movie Type:Comedy 
Movie Format:VHS 
Movie year:1987 
Movie rating:PG 
Movie stars:2 
Movie description:Viewable boredom

重要的事情需要注意上面的代码:

  • 正在形成类XmlParser的对象,以便它可以用于解析XML文档。

  • 解析器被给定XML文件的位置。

  • 对于每个电影元素,我们使用闭包浏览每个子节点并显示相关信息。

对于movie元素本身,我们使用@符号显示附加到movie元素的title属性。

二十六、Groovy JMX

JMX是defacto标准,用于监控与Java虚拟环境有任何关系的所有应用程序。鉴于Groovy直接位于Java之上,Groovy可以利用已经为Java实现的大量工作。

1、监视JVM

可以使用java.lang.management中提供的标准类来执行JVM的监视。以下代码示例说明如何完成此操作。

import java.lang.management.*

def os = ManagementFactory.operatingSystemMXBean 
println """OPERATING SYSTEM: 
	OS architecture = $os.arch 
	OS name = $os.name 
	OS version = $os.version 
	OS processors = $os.availableProcessors 
""" 
 
def rt = ManagementFactory.runtimeMXBean 
println """RUNTIME: 
   	Runtime name = $rt.name 
   	Runtime spec name = $rt.specName 
   	Runtime vendor = $rt.specVendor 
   	Runtime spec version = $rt.specVersion 
   	Runtime management spec version = $rt.managementSpecVersion 
   """ 

def mem = ManagementFactory.memoryMXBean 
def heapUsage = mem.heapMemoryUsage 
def nonHeapUsage = mem.nonHeapMemoryUsage 

println """MEMORY: 
   HEAP STORAGE: 
      	Memory committed = $heapUsage.committed 
      	Memory init = $heapUsage.init 
      	Memory max = $heapUsage.max 
      	Memory used = $heapUsage.used NON-HEAP STORAGE: 
      	Non-heap memory committed = $nonHeapUsage.committed 
      	Non-heap memory init = $nonHeapUsage.init 
      	Non-heap memory max = $nonHeapUsage.max 
      	Non-heap memory used = $nonHeapUsage.used 
   """
  
println "GARBAGE COLLECTION:" 
ManagementFactory.garbageCollectorMXBeans.each { gc ->
   println "	name = $gc.name"
   println "		collection count = $gc.collectionCount"
   println "		collection time = $gc.collectionTime"
   String[] mpoolNames =   gc.memoryPoolNames
	
   mpoolNames.each { 
      mpoolName -> println "		mpool name = $mpoolName"
   } 
}

当代码执行时,输出将根据运行代码的系统而变化。

下面给出了输出的样本:

OPERATING SYSTEM: 
   OS architecture = x86 
   OS name = Windows 7 
   OS version = 6.1 
   OS processors = 4
   
RUNTIME: 
   Runtime name = 5144@Babuli-PC 
   Runtime spec name = Java Virtual Machine Specification 
   Runtime vendor = Oracle Corporation 
   Runtime spec version = 1.7 
   Runtime management spec version = 1.2
   
MEMORY: 
   HEAP STORAGE: 
      Memory committed = 16252928 
      Memory init = 16777216 
      Memory max = 259522560 
      Memory used = 7355840
   
NON-HEAP STORAGE: 
   Non-heap memory committed = 37715968 
   Non-heap memory init = 35815424 
   Non-heap memory max = 123731968 
   Non-heap memory used = 18532232 
   
GARBAGE COLLECTION: 
   name = Copy 
   collection count = 15 
   collection time = 47 
   mpool name = Eden Space 
   mpool name = Survivor Space
		
   name = MarkSweepCompact 
      collection count = 0 
      collection time = 0 
		
      mpool name = Eden Space 
      mpool name = Survivor Space 
      mpool name = Tenured Gen 
      mpool name = Perm Gen 
      mpool name = Perm Gen [shared-ro] 
      mpool name = Perm Gen [shared-rw]

2、监控Tomcat

为了监视tomcat,在启动tomcat时应设置以下参数:

set JAVA_OPTS = -Dcom.sun.management.jmxremote 
Dcom.sun.management.jmxremote.port = 9004
 
-Dcom.sun.management.jmxremote.authenticate=false 
Dcom.sun.management.jmxremote.ssl = false

以下代码使用JMX发现正在运行的Tomcat中的可用MBean,确定哪些是Web模块并提取每个Web模块的处理时间。

import groovy.swing.SwingBuilder
  
import javax.management.ObjectName 
import javax.management.remote.JMXConnectorFactory as JmxFactory 
import javax.management.remote.JMXServiceURL as JmxUrl 
import javax.swing.WindowConstants as WC 
 
import org.jfree.chart.ChartFactory 
import org.jfree.data.category.DefaultCategoryDataset as Dataset 
import org.jfree.chart.plot.PlotOrientation as Orientation 
 
def serverUrl = 'service:jmx:rmi:///jndi/rmi://localhost:9004/jmxrmi' 
def server = JmxFactory.connect(new JmxUrl(serverUrl)).MBeanServerConnection 
def serverInfo = new GroovyMBean(server, 'Catalina:type = Server').serverInfo 
println "Connected to: $serverInfo" 
 
def query = new ObjectName('Catalina:*') 
String[] allNames = server.queryNames(query, null) 

def modules = allNames.findAll { name -> 
   name.contains('j2eeType=WebModule') 
}.collect{ new GroovyMBean(server, it) }
  
println "Found ${modules.size()} web modules. Processing ..." 
def dataset = new Dataset() 
 
modules.each { m ->
   println m.name()
   dataset.addValue m.processingTime, 0, m.path 
}

二十七、Groovy JSON

使用Groovy语言来解析和生成JSON对象。

JSON功能:

功能
JsonSlurper

JsonSlurper是一个将JSON文本或阅读器内容解析为Groovy数据的类

结构,例如地图,列表和原始类型,如整数,双精度,布尔和字符串。

JsonOutput 此方法负责将Groovy对象序列化为JSON字符串。

1、使用JsonSlurper解析数据

JsonSlurper是一个将JSON文本或阅读器内容解析为Groovy数据结构的类,如地图,列表和原始类型,如Integer,Double,Boolean和String。

句法:

def slurper = new JsonSlurper()

JSON slurper将文本或阅读器内容解析为列表和地图的数据结构。

JsonSlurper类自带了一些用于解析器实现的变体。有时,在解析某些字符串时,您可能有不同的要求。让我们举一个例子,其中需要读取从Web服务器的响应返回的JSON。在这种情况下,使用解析器JsonParserLax变量是有益的。此parsee允许在JSON文本中的注释以及没有引号字符串等。要指定此类型的解析器,您需要在定义JsonSlurper的对象时使用JsonParserType.LAX解析器类型。

让我们看下面这个例子。示例是使用http模块从Web服务器获取JSON数据。对于这种类型的遍历,最好的选择是将解析器类型设置为JsonParserLax变体。

http.request( GET, TEXT ) {
   headers.Accept = 'application/json'
   headers.'User-Agent' = USER_AGENT
	
   response.success = { 
      res, rd ->  
      def jsonText = rd.text 
		
      //Setting the parser type to JsonParserLax
      def parser = new JsonSlurper().setType(JsonParserType.LAX)
      def jsonResp = parser.parseText(jsonText)
   }
}

类似地,以下附加的解析器类型在Groovy中可用:

  • JsonParserCharArray解析器基本上采用一个JSON字符串并对底层字符数组进行操作。在值转换期间,它复制字符子数组(称为“斩波”的机制)并单独操作它们。

  • JsonFastParser是JsonParserCharArray的一个特殊变体,是最快的解析器。JsonFastParser也称为索引覆盖解析器。在解析给定的JSON字符串期间,它尽可能努力地避免创建新的字符数组或String实例。它只保留指向底层原始字符数组的指针。此外,它会尽可能晚地推迟对象创建。

  • JsonParserUsingCharacterSource是一个非常大的文件的特殊解析器。它使用一种称为“字符窗口化”的技术来解析具有恒定性能特征的大型JSON文件(大型意味着超过2MB大小的文件)。

1)文本解析

让我们来看看一些如何使用JsonSlurper类的例子。

import groovy.json.JsonSlurper 

class Example {
   static void main(String[] args) {
      def jsonSlurper = new JsonSlurper()
      def object = jsonSlurper.parseText('{ "name": "John", "ID" : "1"}') 
		
      println(object.name);
      println(object.ID);
   } 
}

在上面的例子中,我们是 -

  • 首先创建JsonSlurper类的一个实例

  • 然后我们使用JsonSlurper类的parseText函数来解析一些JSON文本。

  • 当我们获取对象时,您可以看到我们实际上可以通过键访问JSON字符串中的值。

以上程序的输出如下:

John 
1

2)解析整数列表

让我们来看看另一个JsonSlurper解析方法的例子。在下面的示例中,我们将列出整数列表。你会注意到下面的代码,我们可以使用每个的List方法,并传递一个闭包。

import groovy.json.JsonSlurper 
class Example {
   static void main(String[] args) {
      def jsonSlurper = new JsonSlurper()
      Object lst = jsonSlurper.parseText('{ "List": [2, 3, 4, 5] }')
      lst.each { println it }
   } 
}

以上程序的输出如下:

List=[2, 3, 4, 5, 23, 42]

3)解析基本数据类型列表

JSON解析器还支持字符串,数字,对象,true,false和null的原始数据类型。 JsonSlurper类将这些JSON类型转换为相应的Groovy类型。

以下示例显示如何使用JsonSlurper解析JSON字符串。在这里,您可以看到JsonSlurper能够将各个项目解析为各自的基本类型。

import groovy.json.JsonSlurper 
class Example {

   static void main(String[] args) {
      def jsonSlurper = new JsonSlurper()
      def obj = jsonSlurper.parseText ''' {"Integer": 12, "fraction": 12.55, "double": 12e13}'''
		
      println(obj.Integer);
      println(obj.fraction);
      println(obj.double); 
   } 
}

以上程序的输出如下:

12 
12.55 
1.2E+14 

2、JsonOutput

现在让我们谈谈如何在Json中打印输出。这可以通过JsonOutput方法来完成。此方法负责将Groovy对象序列化为JSON字符串。

句法:

Static string JsonOutput.toJson(datatype obj)

参数 -参数可以是数据类型的对象 - 数字,布尔,字符,字符串,日期,地图,闭包等。

返回类型 -返回类型是一个JSON字符串。

以下是如何实现这一点的简单示例:

import groovy.json.JsonOutput 
class Example {
   static void main(String[] args) {
      def output = JsonOutput.toJson([name: 'John', ID: 1])
      println(output);  
   }
}

以上程序的输出如下:

{"name":"John","ID":1}

JsonOutput也可以用于普通的旧Groovy对象。在下面的示例中,您可以看到我们实际上是传递Student类型的对象到JsonOutput方法。

import groovy.json.JsonOutput  
class Example {
   static void main(String[] args) {
      def output = JsonOutput.toJson([ new Student(name: 'John',ID:1),
         new Student(name: 'Mark',ID:2)])
      println(output);  
   } 
}
 
class Student {
   String name
   int ID; 
}

以上程序的输出如下:

[{"name":"John","ID":1},{"name":"Mark","ID":2}]

二十八、Groovy DSLS

Groovy允许在顶层语句的方法调用的参数周围省略括号。这被称为“命令链”功能。这个扩展的工作原理是允许一个人链接这种无括号的方法调用,在参数周围不需要括号,也不需要链接调用之间的点。

如果一个调用被执行为bcd,这将实际上等价于a(b).c(d)。

DSL或域特定语言旨在简化以Groovy编写的代码,使得它对于普通用户变得容易理解。以下示例显示了具有域特定语言的确切含义。

def lst = [1,2,3,4] 
print lst

上面的代码显示了使用println语句打印到控制台的数字列表。在域特定语言中,命令将是:

Given the numbers 1,2,3,4
 
Display all the numbers

所以上面的例子显示了编程语言的转换,以满足领域特定语言的需要。

让我们来看一个简单的例子,我们如何在Groovy中实现DSL:

class EmailDsl {  
   String toText 
   String fromText 
   String body 
	
   /** 
   * This method accepts a closure which is essentially the DSL. Delegate the 
   * closure methods to 
   * the DSL class so the calls can be processed 
   */ 
   
   def static make(closure) { 
      EmailDsl emailDsl = new EmailDsl() 
      // any method called in closure will be delegated to the EmailDsl class 
      closure.delegate = emailDsl
      closure() 
   }
   
   /** 
   * Store the parameter as a variable and use it later to output a memo 
   */ 
	
   def to(String toText) { 
      this.toText = toText 
   }
   
   def from(String fromText) { 
      this.fromText = fromText 
   }
   
   def body(String bodyText) { 
      this.body = bodyText 
   } 
}

EmailDsl.make { 
   to "Nirav Assar" 
   from "Barack Obama" 
   body "How are things? We are doing well. Take care" 
}

当我们运行上面的程序,我们将得到以下结果:

How are things? We are doing well. Take care

以下需要注意上面的代码实现:

  • 使用接受闭包的静态方法。这是一个很麻烦的方式来实现DSL。

  • 在电子邮件示例中,类EmailDsl具有make方法。它创建一个实例,并将闭包中的所有调用委派给实例。这是一种机制,其中“to”和“from”节结束了EmailDsl类中的执行方法。

  • 一旦to()方法被调用,我们将文本存储在实例中以便以后格式化。

  • 我们现在可以使用易于为最终用户理解的简单语言调用EmailDSL方法。

二十九、Groovy 数据库

Groovy的groovy-sql模块提供了比当前Java的JDBC技术更高级的抽象。Groovy sql API支持各种各样的数据库,其中一些如下所示。

  • HSQLDB
  • Oracle
  • SQL Server
  • MySQL
  • MongoDB

在我们的示例中,我们将使用MySQL DB作为示例。为了使用MySQL与Groovy,首先要做的是从mysql站点下载MySQL jdbc jar文件。

MySQL的格式如下所示:

mysql-connector-java-5.1.38-bin

然后,确保将上述jar文件添加到工作站中的类路径。

1、数据库连接

在连接到MySQL数据库之前,请确保以下内容 -

  • 你已经创建了一个数据库TESTDB。
  • 您在TESTDB中创建了一个表EMPLOYEE。
  • 此表格包含FIRST_NAME,LAST_NAME,AGE,SEX和INCOME。
  • 用户ID“testuser”和密码“test123”设置为访问TESTDB。
  • 确保已下载mysql jar文件并将该文件添加到类路径。
  • 你已经通过MySQL教程来了解MySQL基础

下面的示例显示如何连接MySQL数据库“TESTDB”。

import java.sql.*; 
import groovy.sql.Sql 

class Example {
   static void main(String[] args) {
      // Creating a connection to the database
      def sql = Sql.newInstance('jdbc:mysql://localhost:3306/TESTDB', 
         'testuser', 'test123', 'com.mysql.jdbc.Driver')
			
      // Executing the query SELECT VERSION which gets the version of the database
      // Also using the eachROW method to fetch the result from the database
   
      sql.eachRow('SELECT VERSION()'){ row ->
         println row[0]
      }
		
      sql.close()  
   } 
} 

运行此脚本时,会产生以下结果:

5.7.10-log 
The Sql.newInstance method is used to establish a connection to the database.

2、创建数据库表

连接到数据库后的下一步是在数据库中创建表。以下示例显示如何使用Groovy在数据库中创建表。Sql类的execute方法用于对数据库执行语句。

import java.sql.*; 
import groovy.sql.Sql 

class Example { 
   static void main(String[] args) {
      // Creating a connection to the database
      def sql = Sql.newInstance('jdbc:mysql://localhost:3306/TESTDB', 'testuser',  
         'test123', 'com.mysql.jdbc.Driver')
			
      def sqlstr = """CREATE TABLE EMPLOYEE ( 
         FIRST_NAME CHAR(20) NOT NULL,
         LAST_NAME CHAR(20),
         AGE INT,
         SEX CHAR(1),
         INCOME FLOAT )""" 
							
      sql.execute(sqlstr);
      sql.close() 
   } 
}

3、插入操作

当您要将记录创建到数据库表中时需要。

以下示例将在employee表中插入一条记录。代码放置在try catch块中,因此如果记录成功执行,事务将提交到数据库。如果事务失败,则执行回滚。

import java.sql.*; 
import groovy.sql.Sql 

class Example {
   static void main(String[] args) { 
      // Creating a connection to the database
      def sql = Sql.newInstance('jdbc:mysql://localhost:3306/TESTDB', 'testuser', 
         'test123', 'com.mysql.jdbc.Driver')
			
      sql.connection.autoCommit = false
		
      def sqlstr = """INSERT INTO EMPLOYEE(FIRST_NAME,
         LAST_NAME, AGE, SEX, INCOME) VALUES ('Mac', 'Mohan', 20, 'M', 2000)""" 
      try {
         sql.execute(sqlstr);
         sql.commit()
         println("Successfully committed") 
      }catch(Exception ex) {
         sql.rollback()
         println("Transaction rollback") 
      }
		
      sql.close()
   } 
}

假设您只想根据条件选择某些行。以下代码显示如何添加参数占位符以搜索值。上面的例子也可以写成参数,如下面的代码所示。 $符号用于定义一个参数,然后可以在执行sql语句时将其替换为值。

import java.sql.*; 
import groovy.sql.Sql
 
class Example {
   static void main(String[] args) {
      // Creating a connection to the database
      def sql = Sql.newInstance('jdbc:mysql://localhost:3306/TESTDB', 'testuser', 
         'test123', 'com.mysql.jdbc.Driver')
			
      sql.connection.autoCommit = false  
      
      def firstname = "Mac"
      def lastname ="Mohan"
      def age = 20
      def sex = "M"
      def income = 2000  
		
      def sqlstr = "INSERT INTO EMPLOYEE(FIRST_NAME,LAST_NAME, AGE, SEX, 
         INCOME) VALUES " + "(${firstname}, ${lastname}, ${age}, ${sex}, ${income} )"
			
      try {
         sql.execute(sqlstr);
         sql.commit()
         println("Successfully committed") 
      } catch(Exception ex) {
         sql.rollback()
         println("Transaction rollback")
      }
		
      sql.close()
   }
}

4、读操作

读操作上的任何数据库是指从数据库中获取一些有用的信息。一旦我们的数据库建立连接,您就可以进行查询到这个数据库中。

读出操作是通过使用SQL类的eachRow方法进行。

句法:

eachRow(GString gstring, Closure closure) 

执行给定的SQL查询调用,结果集的每一行给出闭幕。

参数:

  • GString的 -这需要执行的SQL语句。

  • 封闭 -封闭语句来处理来自读操作retrived行。执行给定的SQL查询调用,结果集的每一行给出闭幕。

下面的代码示例演示了如何来从雇员表中的所有记录。

import java.sql.*; 
import groovy.sql.Sql
 
class Example {
   static void main(String[] args) {
      // Creating a connection to the database
      def sql = Sql.newInstance('jdbc:mysql://localhost:3306/TESTDB', 'testuser', 
         'test123', 'com.mysql.jdbc.Driver')  
			
      sql.eachRow('select * from employee') {
         tp -> 
         println([tp.FIRST_NAME,tp.LAST_NAME,tp.age,tp.sex,tp.INCOME])
      }  
		
      sql.close()
   } 
}

从上面的程序的输出将是:

[Mac, Mohan, 20, M, 2000.0]

5、更新操作

任何数据库上进行更新操作手段来更新一个或多个记录,这已经在数据库中。下面的过程更新过性别为“M”的所有记录。在这里,我们一岁增加所有男子的年龄。

import java.sql.*; 
import groovy.sql.Sql 

class Example {
   static void main(String[] args){
      // Creating a connection to the database
      def sql = Sql.newInstance('jdbc:mysql://localhost:3306/TESTDB', 'testuser', 
         'test@123', 'com.mysql.jdbc.Driver')
			
      sql.connection.autoCommit = false
      def sqlstr = "UPDATE EMPLOYEE SET AGE = AGE + 1 WHERE SEX = 'M'" 
	  
      try {
         sql.execute(sqlstr);
         sql.commit()
         println("Successfully committed")
      }catch(Exception ex) {
         sql.rollback() 
         println("Transaction rollback")
      }
		
      sql.close()
   } 
}

6、删除操作

当你想从数据库中删除一些记录DELETE操作是必需的。以下是从哪里EMPLOYEE年龄超过20删除所有记录的过程。

import java.sql.*; 
import groovy.sql.Sql 

class Example {
   static void main(String[] args) {
      // Creating a connection to the database
      def sql = Sql.newInstance('jdbc:mysql://localhost:3306/TESTDB', 'testuser', 
         'test@123', 'com.mysql.jdbc.Driver')
			
      sql.connection.autoCommit = false
      def sqlstr = "DELETE FROM EMPLOYEE WHERE AGE > 20"
   
      try {
         sql.execute(sqlstr);
         sql.commit()
         println("Successfully committed")
      }catch(Exception ex) {
         sql.rollback()
         println("Transaction rollback")
      }
   
      sql.close()
   } 
}

7、执行事务

事务是确保数据一致性的机制。交易有以下四个属性:

  • 原子性 -事务完成或根本没有任何事情发生。

  • 一致性 -事务必须以一致的状态开始,并使系统保持一致状态。

  • 隔离 -事务的中间结果在当前事务外部不可见。

  • 持久性 -一旦事务提交,即使系统发生故障,影响仍然持续。

这里是一个如何实现事务的简单示例。我们已经从DELETE操作的上一个主题中看到了这个示例。

def sqlstr = "DELETE FROM EMPLOYEE WHERE AGE > 20" 
 
try {
   sql.execute(sqlstr); 
   sql.commit()
   println("Successfully committed") 
}catch(Exception ex) {
   sql.rollback()
   println("Transaction rollback") 
} 
sql.close()

8、提交操作

提交操作是告诉数据库继续操作并完成对数据库的所有更改。

在我们的上述例子中,这是通过下面的语句实现:

sql.commit()

9、回滚操作

如果您对一个或多个更改不满意,并希望完全还原这些更改,请使用回滚方法。在我们上面的例子中,这是通过以下语句实现的:

sql.rollback()

10、断开数据库

要断开数据库连接,使用Close方法。

sql.close()

三十、Groovy 构建器

在软件开发过程中,有时开发人员花费大量时间来创建数据结构,域类,XML,GUI布局,输出流等。有时用于创建这些特定需求的代码导致在许多地方重复相同的代码片段。这是Groovy的建设者发挥作用。Groovy有可以用来创建标准对象和结构的构建器。这些构建器节省了时间,因为开发人员不需要编写自己的代码来创建这些构建器。在本章的教程中,我们将看看groovy中可用的不同构建器。

1、Swing 构建器

在groovy中,还可以使用groovy中提供的swing构建器创建图形用户界面。开发swing组件的主要类是SwingBuilder类。这个类有许多方法创建图形组件,如 -

  • JFrame - 这是用于创建框架元素。

  • JTextField - 这用于创建textfield组件。

让我们看一个简单的例子,如何使用SwingBuilder类创建一个Swing应用程序。在以下示例中,您可以看到以下几点 -

  • 您需要导入groovy.swing.SwingBuilder和javax.swing.*类。

  • 在Swing应用程序中显示的所有组件都是SwingBuilder类的一部分。

  • 对于框架本身,您可以指定框架的初始位置和大小。您还可以指定框架的标题。

  • 您需要将Visibility属性设置为true才能显示框架。

import groovy.swing.SwingBuilder 
import javax.swing.* 

// Create a builder 
def myapp = new SwingBuilder()

// Compose the builder 
def myframe = myapp.frame(title : 'Tutorials Point', location : [200, 200], 
   size : [400, 300], defaultCloseOperation : WindowConstants.EXIT_ON_CLOSE {         
      label(text : 'Hello world')
   } 
	
// The following  statement is used for displaying the form 
frame.setVisible(true)

上述程序的输出如下。以下输出显示JFrame以及带有Hello World文本的JLabel。

让我们看看下一个用文本框创建输入屏幕的例子。在以下示例中,我们要创建一个包含学生姓名,主题和学校名称文本框的表单。在以下示例中,您可以看到以下要点:

  • 我们正在为屏幕上的控件定义一个布局。在这种情况下,我们使用网格布局。
  • 我们正在为我们的标签使用对齐属性。
  • 我们使用textField方法在屏幕上显示文本框。
import groovy.swing.SwingBuilder 
import javax.swing.* 
import java.awt.*
 
// Create a builder 
def myapp = new SwingBuilder() 

// Compose the builder 
def myframe = myapp.frame(title : 'Tutorials Point', location : [200, 200], 
   size : [400, 300], defaultCloseOperation : WindowConstants.EXIT_ON_CLOSE) { 
      panel(layout: new GridLayout(3, 2, 5, 5)) { 
         label(text : 'Student Name:', horizontalAlignment : JLabel.RIGHT) 
         textField(text : '', columns : 10) 
			
         label(text : 'Subject Name:', horizontalAlignment : JLabel.RIGHT) 
         textField(text : '', columns : 10)
			
         label(text : 'School Name:', horizontalAlignment : JLabel.RIGHT) 
         textField(text : '', columns : 10) 
      } 
   } 
	
// The following  statement is used for displaying the form 
myframe.setVisible(true)

以上程序的输出如下:

2、事件处理程序

现在让我们看看事件处理程序。事件处理程序用于按钮,当按下按钮时执行某种处理。每个按钮伪方法调用包括actionPerformed参数。这表示呈现为闭包的代码块。

让我们来看看我们下一个用2个按钮创建屏幕的例子。当按下任一按钮时,相应的消息被发送到控制台屏幕。在以下示例中,您可以看到以下要点 -

  • 对于定义的每个按钮,我们使用actionPerformed方法并定义一个闭包,以便在单击按钮时向控制台发送一些输出。

import groovy.swing.SwingBuilder 
import javax.swing.* 
import java.awt.* 

def myapp = new SwingBuilder()
  
def buttonPanel = {
   myapp.panel(constraints : BorderLayout.SOUTH) {
	
      button(text : 'Option A', actionPerformed : {
         println 'Option A chosen'
      })
		
      button(text : 'Option B', actionPerformed : {
         println 'Option B chosen'
      })
   }
}
  
def mainPanel = {
   myapp.panel(layout : new BorderLayout()) {
      label(text : 'Which Option do you want', horizontalAlignment : 
      JLabel.CENTER,
      constraints : BorderLayout.CENTER)
      buttonPanel()
   }
}
  
def myframe = myapp.frame(title : 'Tutorials Point', location : [100, 100],
   size : [400, 300], defaultCloseOperation : WindowConstants.EXIT_ON_CLOSE){
      mainPanel()
   }
	
myframe.setVisible(true)

上述程序的输出如下。单击任一按钮时,所需的消息将发送到控制台日志屏幕。

上述示例的另一个变体是定义可以充当处理程序的方法。在下面的例子中,我们定义了DisplayA和DisplayB的2个处理程序。

import groovy.swing.SwingBuilder 
import javax.swing.* 
import java.awt.* 

def myapp = new SwingBuilder()
  
def DisplayA = {
   println("Option A") 
} 

def DisplayB = {
   println("Option B")
}

def buttonPanel = {
   myapp.panel(constraints : BorderLayout.SOUTH) {
      button(text : 'Option A', actionPerformed : DisplayA) 
      button(text : 'Option B', actionPerformed : DisplayB)
   }
}  

def mainPanel = {
   myapp.panel(layout : new BorderLayout()) {
      label(text : 'Which Option do you want', horizontalAlignment : JLabel.CENTER,
      constraints : BorderLayout.CENTER)
      buttonPanel()
   }
}  

def myframe = myapp.frame(title : 'Tutorials Point', location : [100, 100],
   size : [400, 300], defaultCloseOperation : WindowConstants.EXIT_ON_CLOSE) {
      mainPanel()
   } 
	
myframe.setVisible(true) 

上述程序的输出将保持与前面的示例相同。

3、DOM生成器

DOM构建器可用于解析HTML,XHTML和XML,并将其转换为W3C DOM树。

以下示例显示如何使用DOM构建器。

String records = '''
   <library>
	
      <Student>
         <StudentName division = 'A'>Joe</StudentName>
         <StudentID>1</StudentID>
      </Student>
	  
      <Student>
         <StudentName division = 'B'>John</StudentName>
         <StudentID>2</StudentID>
      </Student>
	  
      <Student>
         <StudentName division = 'C'>Mark</StudentName>
         <StudentID>3</StudentID>
      </Student>
		
   </library>'''
   
def rd = new StringReader(records) 
def doc = groovy.xml.DOMBuilder.parse(rd)

4、JsonBuilder

JsonBuilder用于创建json类型的对象。

以下示例显示如何使用Json构建器。

def builder = new groovy.json.JsonBuilder() 

def root = builder.students {
   student {
      studentname 'Joe'
      studentid '1'
		
      Marks(
         Subject1: 10,
         Subject2: 20,
         Subject3:30,
      )
   } 
} 
println(builder.toString());

上述程序的输出如下。输出clearlt显示Jsonbuilder能够从结构化的节点集合构建json对象。

{"students":{"student":{"studentname":"Joe","studentid":"1","Marks":{"Subject1":10,
"S ubject2":20,"Subject3":30}}}}

jsonbuilder还可以接受一个列表并将其转换为json对象。以下示例说明如何完成此操作。

def builder = new groovy.json.JsonBuilder() 
def lst = builder([1, 2, 3]) 
println(builder.toString());

上述程序的输出如下:

[1,2,3]

jsonBuilder也可以用于类。以下示例显示类的对象如何成为json构建器的输入。

def builder = new groovy.json.JsonBuilder() 

class Student {
   String name  
} 

def studentlist = [new Student (name: "Joe"), new Student (name: "Mark"), 
   new Student (name: "John")] 
	
builder studentlist, { Student student ->name student.name} 
println(builder)

上述程序的输出如下:

[{"name":"Joe"},{"name":"Mark"},{"name":"John"}] 

5、NodeBuilder

NodeBuilder用于创建Node对象的嵌套树以处理任意数据。

下面显示了Nodebuilder的用法示例:

def nodeBuilder = new NodeBuilder() 

def studentlist = nodeBuilder.userlist {
   user(id: '1', studentname: 'John', Subject: 'Chemistry')
   user(id: '2', studentname: 'Joe', Subject: 'Maths')
   user(id: '3', studentname: 'Mark', Subject: 'Physics') 
} 

println(studentlist)

6、FileTreeBuilder

FileTreeBuilder是一个从规范生成文件目录结构的构建器。

以下是如何使用FileTreeBuilder的示例:

tmpDir = File.createTempDir() 
def fileTreeBuilder = new FileTreeBuilder(tmpDir) 

fileTreeBuilder.dir('main') {
   dir('submain') {
      dir('Tutorial') {
        file('Sample.txt', 'println "Hello World"')
      }
   } 
}

从上述代码的执行,将在文件夹main / submain / Tutorial中创建一个名为sample.txt的文件。而sample.txt文件将具有“Hello World”的文本。

三十一、Groovy 命令行

被称为groovysh的Groovy shell可以很容易地用于评估groovy表达式,定义类和运行简单的程序。当安装Groovy时,将安装命令行shell。

以下是Groovy中提供的命令行选项:

命令行参数 全名 描述
-C --color [= FLAG] 启用或禁用使用ANSI颜色
-D --define = NAME = VALUE 定义系统属性
-T --terminal = TYPE 指定要使用的终端TYPE
-V --version 显示版本
-classpath 指定在哪里找到类文件 - 必须是第一个参数
-cp --classpath 别名“-classpath”
-d --debug --debug启用调试输出
-e --evaluate=arg 启动交互式会话时,评估选项指标
-H --help 显示此帮助消息
-q --quiet 禁止多余的输出
-v --verbose 启用详细输出

以下快照显示了在Groovy shell中执行的表达式的一个简单示例。在下面的例子中,我们只是在groovy shell中打印“Hello World”。

1、类和函数

在命令提示符下定义一个类是很容易的,创建一个新对象并调用类上的方法。下面的示例显示如何实现。在下面的示例中,我们使用简单的方法创建一个简单的Student类。在命令提示符本身中,我们正在创建一个类的对象并调用Display方法。

很容易在命令提示符中定义一个方法并调用该方法。注意,该方法是使用def类型定义的。还要注意,我们已经包括一个称为名称的参数,然后在调用Display方法时将其替换为实际值。下面的示例显示如何实现。

2、命令

shell有许多不同的命令,提供对shell环境的丰富访问。以下是他们的名单和他们做什么。

命令 命令说明
:help (:h)显示此帮助消息
? (:?)别名为::帮助
:exit (:x)退出shell
:quit (:q)别名为::exit
import (:i)将一个类导入命名空间
:display (:d)显示当前缓冲区
:clear (:c)清除缓冲区并复位提示计数器
:show (:S)显示变量,类或导入
:inspect (:n)使用GUI对象浏览器检查变量或最后一个结果
:purge (:p)清除变量,类,导入或首选项
:edit (:e)编辑当前缓冲区
:load (:l)将文件或URL装入缓冲区
. (:.)别名为::load
.save (:s)将当前缓冲区保存到文件
.record (:r)将当前会话记录到文件
:alias (:a)创建别名
:set (:=)设置(或列表)首选项
:register (:rc)使用shell注册新命令
:doc (:D)打开一个浏览器窗口,显示参数的文档
:history (:H)显示,管理和撤回编辑行历史记录

三十二、Groovy 单元测试

面向对象系统的基本单元是类。因此单元测试由一个类中的testig组成。所采用的方法是创建被测试类的对象,并使用它来检查所选方法是否按预期执行。不是每个方法都可以测试,因为并不总是测试每一件事情。但是应该对关键和关键方法进行单元测试。

JUnit是一个开源测试框架,是Java代码自动化单元测试的公认行业标准。幸运的是,JUnit框架可以很容易地用于测试Groovy类。所需要的只是扩展作为标准Groovy环境一部分的GroovyTestCase类。 Groovy测试用例类基于Junit测试用例。

1、编写一个简单的Junit测试用例

假设我们在应用程序类文件中定义了以下类:

class Example {
   static void main(String[] args) {
      Student mst = new Student();
      mst.name = "Joe";
      mst.ID = 1;
      println(mst.Display())
   } 
} 
 
public class Student {
   String name;
   int ID;
	
   String Display() {
      return name +ID;
   }  
}

低于上述程序的输出中给出:

Joe1

现在假设我们想为Student类写一个测试用例。典型的测试用例如下所示。

以下几点需要注意以下代码 :

  • 测试用例类扩展了GroovyTestCase类
  • 我们使用assert语句来确保Display方法返回正确的字符串。
class StudentTest extends GroovyTestCase {
   void testDisplay() {
      def stud = new Student(name : 'Joe', ID : '1')
      def expected = 'Joe1'
      assertToString(stud.Display(), expected)
   }
}

2、Groovy测试套件

通常,随着单元测试的数量增加,将难以一个接一个地继续执行所有测试用例。因此,Groovy提供了一个创建测试套件的工具,可以将所有测试用例封装到一个逻辑单元中。以下代码段显示了如何实现这一点。

应该注意以下事情的代码 :

  • GroovyTestSuite用于将所有测试用例封装在一起。

  • 在下面的例子中,我们假设我们有两个测试用例文件,一个叫StudentTest,另一个是EmployeeTest,它包含所有必要的测试。

import groovy.util.GroovyTestSuite 
import junit.framework.Test 
import junit.textui.TestRunner 

class AllTests { 
   static Test suite() { 
      def allTests = new GroovyTestSuite() 
      allTests.addTestSuite(StudentTest.class) 
      allTests.addTestSuite(EmployeeTest.class) 
      return allTests 
   } 
} 

TestRunner.run(AllTests.suite())

三十三、Groovy 模板引擎

Groovy的模板引擎的操作方式类似于邮件合并(从数据库自动添加名称和地址到字母和信封,以便于将邮件,特别是广告发送到许多地址),但是它更加通用。

1、字符串中的简单模板

如果你采用下面的简单例子,我们首先定义一个名称变量来保存字符串“Groovy”。在println语句中,我们使用$符号来定义可以插入值的参数或模板。

def name = "Groovy" 
println "This Tutorial is about ${name}"

如果上面的代码在groovy中执行,将显示以下输出。输出清楚地显示$名称被由def语句分配的值替换。

2、简单模板引擎

以下是SimpleTemplateEngine的示例,它允许您在模板中使用类似于JSP的scriptlet和EL表达式,以生成参数化文本。模板引擎允许绑定参数列表及其值,以便可以在具有定义的占位符的字符串中替换它们。

def text ='This Tutorial focuses on $TutorialName. In this tutorial you will learn 

about $Topic'  

def binding = ["TutorialName":"Groovy", "Topic":"Templates"]  
def engine = new groovy.text.SimpleTemplateEngine() 
def template = engine.createTemplate(text).make(binding) 

println template

如果上面的代码在groovy中执行,将显示以下输出。

现在让我们使用XML文件的模板功能。作为第一步,让我们将下面的代码添加到一个名为Student.template的文件中。在以下文件中,您将注意到,我们尚未添加元素的实际值,而是添加占位符。所以$ name,$ is和$ subject都被放置为占位符,需要在运行时替换。

<Student> 
   <name>${name}</name> 
   <ID>${id}</ID> 
   <subject>${subject}</subject> 
</Student>

现在,让我们添加我们的Groovy脚本代码来添加功能,可以使用实际值替换上面的模板。应该注意以下事项关于以下代码。

  • 占位符到实际值的映射通过绑定和SimpleTemplateEngine完成。绑定是一个映射,占位符作为键,替换值作为值。

import groovy.text.* 
import java.io.* 

def file = new File("D:/Student.template") 
def binding = ['name' : 'Joe', 'id' : 1, 'subject' : 'Physics']
				  
def engine = new SimpleTemplateEngine() 
def template = engine.createTemplate(file) 
def writable = template.make(binding) 

println writable

如果上面的代码在groovy中执行,将显示以下输出。从输出中可以看出,在相关占位符中成功替换了值。

<Student> 
   <name>Joe</name> 
   <ID>1</ID> 
   <subject>Physics</subject> 
</Student>

3、StreamingTemplateEngine

StreamingTemplateEngine引擎是Groovy中可用的另一个模板引擎。这类似于SimpleTemplateEngine,但是使用可写的闭包创建模板,使其对于大模板更具可扩展性。特别是这个模板引擎可以处理大于64k的字符串。

以下是如何使用StreamingTemplateEngine的示例:

def text = '''This Tutorial is <% out.print TutorialName %> The Topic name 

is ${TopicName}''' 
def template = new groovy.text.StreamingTemplateEngine().createTemplate(text)
  
def binding = [TutorialName : "Groovy", TopicName  : "Templates",]
String response = template.make(binding) 
println(response)

如果上面的代码在groovy中执行,将显示以下输出。

This Tutorial is Groovy The Topic name is Templates

4、XMLTemplateEngine

XmlTemplateEngine用于模板方案,其中模板源和预期输出都是XML。模板使用正常的$ {expression}和$ variable表示法将任意表达式插入到模板中。

以下是如何使用XMLTemplateEngine的示例:

def binding = [StudentName: 'Joe', id: 1, subject: 'Physics'] 
def engine = new groovy.text.XmlTemplateEngine() 

def text = '''
   <document xmlns:gsp='http://groovy.codehaus.org/2005/gsp'>
      <Student>
         <name>${StudentName}</name>
         <ID>${id}</ID>
         <subject>${subject}</subject>
      </Student>
   </document> 
''' 

def template = engine.createTemplate(text).make(binding) 
println template.toString()

如果上面的代码在groovy中执行,将显示以下输出:

<document> 
   <Student> 
      <name> 
         Joe 
      </name> 
      <ID> 
         1 
      </ID> 
      <subject> 
         Physics 
      </subject>
   </Student> 
</document> 

三十四、Groovy 元对象编程

元对象编程或MOP可以用于动态调用方法,并且可以即时创建类和方法。

那么这是什么意思呢?让我们考虑一个叫Student的类,它是一个没有成员变量或方法的空类。假设你必须在这个类上调用以下语句。

Def myStudent = new Student() 
myStudent.Name = ”Joe”; 
myStudent.Display()

现在在元对象编程中,即使类没有成员变量Name或方法Display(),上面的代码仍然可以工作。

这如何工作?那么,为了这个工作,一个人必须实现GroovyInterceptable接口挂钩到Groovy的执行过程。以下是该接口的可用方法。

Public interface GroovyInterceptable { 
   Public object invokeMethod(String methodName, Object args) 
   Public object getproperty(String propertyName) 
   Public object setProperty(String propertyName, Object newValue) 
   Public MetaClass getMetaClass() 
   Public void setMetaClass(MetaClass metaClass) 
}

所以在上面的接口描述中,假设你必须实现invokeMethod(),它会被调用的每个方法,要么存在或不存在。

1、缺失属性

所以,让我们看一个例子,我们如何为缺失的属性实现元对象编程。

以下键应该注意以下代码:

  • 类Student没有定义名为Name或ID的成员变量。

  • 类Student实现GroovyInterceptable接口。

  • 有一个称为dynamicProps的参数,将用于保存即时创建的成员变量的值。

  • 方法getproperty和setproperty已被实现以在运行时获取和设置类的属性的值。

class Example {
   static void main(String[] args) {
      Student mst = new Student();
      mst.Name = "Joe";
      mst.ID = 1;
		
      println(mst.Name);
      println(mst.ID);
   }
}

class Student implements GroovyInterceptable { 
   protected dynamicProps=[:]
	
   void setProperty(String pName,val) {
      dynamicProps[pName] = val
   }
   
   def getProperty(String pName) {
      dynamicProps[pName]
   } 
} 

以下代码的输出将是:

Joe 
1

2、缺失方法

所以,让我们看一个例子,我们如何为缺失的属性实现元对象编程。以下键应该注意下面的代码 -

  • 类学生现在实现invokeMethod方法,它被调用,而不管该方法是否存在。

class Example {
   static void main(String[] args) {
      Student mst = new Student();
      mst.Name = "Joe";
      mst.ID = 1;
		
      println(mst.Name);
      println(mst.ID);
      mst.AddMarks();
   } 
}
 
class Student implements GroovyInterceptable {
   protected dynamicProps = [:]  
    
   void setProperty(String pName, val) {
      dynamicProps[pName] = val
   } 
   
   def getProperty(String pName) {
      dynamicProps[pName]
   }
   
   def invokeMethod(String name, Object args) {
      return "called invokeMethod $name $args"
   }
}

以下代码的输出如下所示。请注意,即使方法Display不存在,也没有缺少方法异常的错误。

Joe 
1 

3、元类

此功能与MetaClass实现相关。在默认实现中,您可以访问字段而不调用它们的getter和setter。以下示例显示如何通过使用metaClass函数,我们能够更改类中的私有变量的值。

class Example {
   static void main(String[] args) {
      Student mst = new Student();
      println mst.getName()
      mst.metaClass.setAttribute(mst, 'name', 'Mark')
      println mst.getName()
   } 
} 

class Student {
   private String name = "Joe";
	
   public String getName() {
      return this.name;
   } 
}

以下代码的输出将是:

Joe 
Mark

4、方法缺失

Groovy支持methodMissing的概念。此方法与invokeMethod的不同之处在于,它仅在失败的方法分派的情况下被调用,当没有找到给定名称和/或给定参数的方法时。以下示例显示如何使用methodMissing。

class Example {
   static void main(String[] args) {
      Student mst = new Student();
      mst.Name = "Joe";
      mst.ID = 1;
		
      println(mst.Name);
      println(mst.ID);
      mst.AddMarks();
   } 
} 

class Student implements GroovyInterceptable {
   protected dynamicProps = [:]  
    
   void setProperty(String pName, val) {
      dynamicProps[pName] = val
   }
   
   def getProperty(String pName) {
      dynamicProps[pName]
   }
   
   def methodMissing(String name, def args) {         
      println "Missing method"
   }  
}

以下代码的输出将是:

Joe 
1 
Missing method 

三十五、Groovy Booleans和Shebang

1、Booleans

Groovy Booleans(布尔值)是用来表示真值的特殊数据类型:true和false。 可使用这种数据类型,简单地跟踪真/假的条件(conditions)。

布尔值就像任何其他数据类型一样,可以存储在变量中,可以被指派到字段:

def myBooleanVariable = true

boolean untypedBooleanVar = false

booleanField = true

true和false是仅有的两个布尔值基元。 但更复杂的布尔表达式可以使用逻辑运算符来表示。

此外,Groovy中具有强制非布尔对象转化为布尔值的特殊规则(通常被称为Groovy Truth)。

2、Shebang行

除了单行注释外, 还有一种被特别的行注释, 通常被称作shebang行,它通常在UNIX系统中被认知,它容许脚本直接在命令行中运行那些你已经安装的Groovy和那些已经在PATH中可用的groovy命令。

#!/usr/bin/env groovy

println "Hello from the shebang line"
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Groovy语言详解 的相关文章

  • JVM跳转指令的偏移量怎么会是32768呢?

    在写一个回答有关 JVM 字节码偏移量的问题 https stackoverflow com a 30240357 3182664 我注意到 javac 的行为和生成的类文件中有一些我无法解释的内容 当编译这样的类时 class FarJu
  • 无法识别的选项: - 无法创建 Java 虚拟机

    我正在尝试运行我的 jarLinux 服务器上的文件 这些是我正在运行的命令 JAVA HOME app local opt jdk packages jdk1 6 0 30 export PATH JAVA HOME bin PATH c
  • 在最近的 JVM 中,不可见引用仍然是一个问题吗?

    我正在读书Java 平台性能 http java sun com docs books performance 1st edition html JPAppGC fm html 遗憾的是 自从我最初提出这个问题以来 该链接似乎已经从互联网上
  • G1 GC 单个、非常长的年轻 GC 发生且 ParallelGCThreads=1

    I set ParallelGCThreads 1并使用G1 GC 所有其他JVM设置为默认设置 我跑PageRank在 Spark 1 5 1 上 有两个 EC2 节点 每个节点有 100 GB 堆 我的堆使用情况图如下 红色区域 年轻代
  • JVM 内存类型

    我正在做一个监控项目 我们有监控软件正在运行并从服务器重新收集指标 一切工作正常 但我们需要一些有关 JVM 内存使用情况详细信息 我们有一些具有不同内存类型的列 我们需要知道这些是什么 Heap Non Heap Usage Peak C
  • 为什么要实现finalize()?

    我已经阅读了很多 Java 新手问题finalize 令人困惑的是 没有人真正明确表示 Finalize 是一种不可靠的清理资源的方法 我看到有人评论说他们用它来清理连接 这真的很可怕 因为接近保证连接关闭的唯一方法是最后实现 try ca
  • IntelliJ 调试:暂停整个虚拟机,然后进入单线程

    我正在调试一个具有大量线程的应用程序 我的断点设置为暂停整个虚拟机 当线程遇到其中一个断点时 我想使用 Step Over 但这似乎会恢复整个虚拟机 直到该步骤完成 如果我可以只单步执行到达断点的单个线程 那确实会有帮助 在 Intelli
  • 如果只有完全限定名称,如何获取 java 类的二进制名称?

    反射类和方法以及类加载器等需要使用所谓的 二进制 类名称 问题是 如果只有完全限定名称 即在源代码中使用的名称 如何获得二进制名称 例如 package frege public static class RT public static
  • 显示JVM中当前运行的所有线程组和线程

    所以我的任务是显示所有线程组以及当前在 JVM 中运行的属于这些组的所有线程 输出时应首先显示线程组 然后在下面显示该组中的所有线程 这是针对所有线程组完成的 目前 我的代码将仅显示每个线程组 然后显示每个线程 但我不确定如何达到我所描述的
  • Lambda 性能改进,Java 8 与 11

    我对 lambda 与方法参考运行了一些 JMH 测试 看起来类似于 IntStream reduce Integer max vs IntSream reduce i1 i2 gt Integer max i1 i2 我注意到 在 Jav
  • 最近有关于 JVM 的书吗? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 非活动状态下的 Spring Boot 堆使用情况

    我在本地部署了一个非常简单的 spring boot 应用程序 它只有一个类 控制器 差不多就这样了 我注意到堆分配并不稳定 并且有峰值和突然下降 为什么会这样 我没有对应用程序进行过一次调用 A view from VisualVM 事实
  • HotSpot使用的Mark-Compact算法是什么?

    当阅读 Mark Compact 章节时垃圾收集手册 https rads stackoverflow com amzn click com 1420082795 提出了一系列替代方案 但其中大多数看起来很旧 理论上 例如 2 指压缩和 L
  • java.library.path 中没有字体管理器

    以下代码在我的桌面上运行得很好 BufferedImage image new BufferedImage width height BufferedImage TYPE INT RGB Graphics g image getGraphi
  • 在intellij中为java启用ssl调试

    从我的问题开始 上一期尝试通过 tls ssl 发送 java 邮件 https stackoverflow com questions 39259578 javamail gmail issue ready to start tls th
  • JVM 是否会内联对象的实例变量和方法?

    假设我有一个非常紧密的内部循环 每次迭代都会访问和改变一个簿记对象 该对象存储有关算法的一些简单数据 并具有用于操作它的简单逻辑 簿记对象是私有的和最终的 并且它的所有方法都是私有的 最终的和 inline 下面是一个示例 Scala 语法
  • jvm 如何以及何时何地更改 Linux 的最大打开文件值?

    在linux中 每个登录用户的每个进程的最大打开文件数有限制 如下所示 ulimit n 1024 当我学习java nio时 我想检查这个值 因为channel在Linux中也是一个文件 所以我编写了一个客户端代码来不断创建socketC
  • Scala REPL 中的递归重载语义 - JVM 语言

    使用 Scala 的命令行 REPL def foo x Int Unit def foo x String Unit println foo 2 gives error type mismatch found Int 2 required
  • 如何在Java中计算对象的数字年龄[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想知道Java中对象的年龄 当我们使用new关键字时 Java中用户定义的对象被创建 但是什么时候它会被销毁 是跨越JVM的perm
  • 容器中的 JVM 计算处理器错误?

    最近我又做了一些研究 偶然发现了这一点 在向 OpenJDK 团队抱怨之前 我想看看是否有其他人观察到这一点 或者不同意我的结论 因此 众所周知 JVM 长期以来忽略了应用于 cgroup 的内存限制 众所周知 现在从 Java 8 更新某

随机推荐

  • 变频调速系统c语言编程,基于8098单片机的SPWM变频调速系统

    数字控制的交流调速系统所选用的微处理器 功率器件及产生PWM波的方法是影响交流调速系统性能好坏的直接因素 在介绍了正弦脉宽调制 SPWM 技术的基础上 设计了一种以8098单片机作为控制器 以智能功率模块IPM为开关器件的变频调速系统 通过
  • 小样本学习(Few-shot Learning)综述

    作者丨耿瑞莹 李永彬 黎槟华 单位丨阿里巴巴智能服务事业部小蜜北京团队 分类非常常见 但如果每个类只有几个标注样本 怎么办呢 笔者所在的阿里巴巴小蜜北京团队就面临这个挑战 我们打造了一个智能对话开发平台 Dialog Studio 以赋能第
  • [Flutter]封装了个Toast组件

    Flutter官方插件市场上已经有了很多成熟的Toast组件 如 fluttertoast 等等 使用了一年多的Flutter框架 一时兴起 自己封装了一个简单的Toast组件 注 本人觉得 自动关闭的时候 不宜使用 Navigator p
  • 西门子PLC S7-1200的硬件中断组织块简介

    西门子PLC S7 1200系列是一款中小型西门子PLC 可以在各种自动化项目中进行应用 S7 1200系列设计较为紧凑 经济性较好 而且指令功能较为强大 因此在各种自动化控制解决方案中有较广泛的应用 作为西门子PLC S7 200系列的升
  • [1218]hive之Map Join使用方法

    文章目录 介绍 mapjoin的使用方法 介绍 MAPJION会把小表全部加载到内存中 在map阶段直接拿另外一个表的数据和内存中表数据做匹配 由于在map端是进行了join操作 省去了reduce运行的时间 算是hive中的一种优化 如上
  • 开放原子训练营(第三季)inBuilder低代码开发实验室之探秘

    一 活动介绍 以开放原子训练营为主办方的inBuilder低代码实验室活动现已开启 参与者无论身居计算机业界 偏好低代码开发抑或是普通用户 均可在社区版inBuilder低代码开发平台 一款基于UBML开源项目的广泛适用的发行版 中尝试向导
  • ECMAScript2020 可选链操作符(?.)的应用

    一 前言 const programmer user lin department name 技术部 getSite return 在以前的语法中 想要获得深层次的属性或方法 如果不做前置校验的话 那么就很容易出现这种错误 这可能会导致你整
  • MFC 之 重绘按键Cbutton

    上次我们学习了如何美化对话框的界面 这次我们为上次的对话框添加两个按钮 一个是关闭按钮 另一个是最小化按钮 好 现在我们先看一下效果 是不是很难看 因为我们的对话框美化了 所以我们的按钮也要美化 因为采用贴图的方式来美化 所以 我先给出这两
  • 笔试面试算法经典--矩阵的最短路径和(Java)

    题目 给定一个矩阵m 从左上角开始每次只能向右或者向下走 最后到达右下角的位置 路径上所有的数字累加起来就是路径和 返回所有路径中最小的路径和 例子 给定m如下 1 3 5 9 8 1 3 4 5 0 6 1 8 8 4 0 路径1 3 1
  • 信号去噪 - 基于SVD实现数字信号降噪含Matlab源码

    信号去噪 基于SVD实现数字信号降噪含Matlab源码 介绍 信号处理中的一个重要问题是如何降噪 这在各种应用领域中都有非常重要的作用 奇异值分解 SVD 是一种广泛使用的信号处理技术 可以用于有效地降低信号噪声 本文将介绍如何使用SVD进
  • Elasticsearch 安装及启动【Windows】

    一 下载 Elasticsearch 官网下载地址 https www elastic co cn downloads past releases elasticsearch 选择自己所需版本进行下载 这里以Elasticsearch 8
  • 【操作系统】王道考研 p64-66 IO软件层次结构、IO核心子系统、假脱机技术(SPOOLing技术)

    IO软件层次结构 IO核心子系统 假脱机技术 SPOOLing技术 以下是IO软件层次结构的内容 知识总览 用户层软件 实现了与用户交互的接口 将用户的请求翻译为格式化的IO请求 并通过 系统调用 请求操作系统内核的服务 设备独立性软件 又
  • PyQt5 QTableWidget内容复制功能

    为了更快速的将QTableWidget的内容复制到剪贴板 只需重写这个控件的keyPressEvent event 废话不多说 直接上代码 复制功能 def keyPressEvent self event Ctrl C复制表格内容 if
  • 大语言模型浅探一

    目录 1 前言 2 GPT模型解码 3 InstructGPT 4 基于RWKV微调模型 4 1 RWKV简介 4 2 增量预训练 4 3 SFT微调 4 4 RM和PPO 5 测试 6 总结 1 前言 近来 人工智能异常火热 ChatGP
  • 如何把“自己的”网络中的conv2d替换为dcnv2

    1 dcnv2的实现测试了两种 一种是官方版dcnv2 git链接 https github com CharlesShang DCNv2 git 编译直接cd到DCNv2 然后 make sh即可 第二种是mmcv ops modulat
  • redis单机版部署

    目录 1 下载版本 2 上传解压 3 安装依赖包 4 进入redis目录 执行编译 5 创建相应目录 6 配置redis conf 7 启动redis 8 配置redis开机自启 1 下载版本 以下是我使用的版本 redis 4 0 1 链
  • 黑盒测试用例设计方法案例与练习题

    1 等价类 案例 登录功能 用户名和密码登录 以在线考试系统为例 年龄字段输入 2 网站注册页面年龄输入要求 某网站前台用户注册页面 其中有年龄字段的输入 要求输入1 150之间的正整数 输入条件 有效等价类 取值 编号 无效等价类 取值
  • 4.1.2 到底在规划、设计什么

    最后更新2021 08 19 以最简单 最朴素的语言说 规划 设计就是在拼凑一个框架 虚拟填补小说的事实 让最后一切发生的合情合理 顺乎自然 没有例外 规划 不能将悲剧的结局变成喜剧收尾 但依靠编剧的功底 能够将剧情玩弄于股掌之间 让每位观
  • 天梯赛省赛选拔赛复盘

    很可惜的一场比赛 两小时调H题没调出来T T 如果调出来就能被选上了 无限Sad 意难平 希望蓝桥杯不留遗憾 文章目录 A题 蜗牛与井 签到 B题 火力覆盖 贪心 数学 C题 ZZ的函数 D题 自然溢出 思维 数学 E题 小y的棋子 F题
  • Groovy语言详解

    一 Groovy 概述 Groovy是一种基于Java平台的面向对象语言 Groovy 1 0于2007年1月2日发布 其中Groovy 2 4是当前的主要版本 Groovy通过Apache License v 2 0发布 Groovy中有