正则表达式是用于在文本中查找子字符串的模式。Groovy使用~“regex”表达式本地支持正则表达式。引号中包含的文本表示用于比较的表达式。
可以创建一个正则表达式对象:
def regex = ~"Groovy"
当定义正则表达式时,可以使用以下特殊字符
有两个特殊的位置字符用于表示一行的开始和结束:caret(∧)和美元符号($)。
正则表达式也可以包括量词。加号(+)表示一次或多次,应用于表达式的前一个元素。星号(*)用于表示零个或多个出现。问号(?)表示零或一次。
元字符{和}用于匹配前一个字符的特定数量的实例。
在正则表达式中,句点符号(。)可以表示任何字符。这被描述为通配符。
正则表达式可以包括字符类。一组字符可以作为简单的字符序列,包含在元字符[和]中,如[aeiou]中。对于字母或数字范围,可以使用[a-z]
或[a-mA-M]
中的短划线分隔符。字符类的补码由方括号内的前导插入符号表示,如[∧a-z]
中所示,并表示除指定的字符以外的所有字符。
与Java类似
与Java类似
与Java类似
特征是语言的结构构造,允许
行为的组成
接口的运行时实现
与静态类型检查/编译的兼容性
它们可以被看作是承载默认实现和状态的接口。使用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()); //Display Marks
println(st.DisplayTotal()); //Display Total
}
}
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;
}
属性
特征可以定义属性。下面给出了具有属性的trait的示例。
在以下示例中,integer 类型的 Marks1 是一个属性。
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
println(st.DisplayMarks()); //10
println(st.DisplayTotal()); // Display Total
}
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
}
}
行为的构成
特征可以用于以受控的方式实现多重继承,避免钻石问题。在下面的代码示例中,我们定义了两个特征 - Marks 和 Total。我们的 Student 类实现了两个特征。由于学生类扩展了这两个特征,它能够访问这两种方法 - DisplayMarks 和 DisplayTotal。
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
println(st.DisplayMarks()); //Marks1
println(st.DisplayTotal()); //Total
}
}
trait Marks {
void DisplayMarks() {
println("Marks1");
}
}
trait Total {
void DisplayTotal() {
println("Total");
}
}
class Student implements Marks,Total {
int StudentID
}
扩展特征
特征可能扩展另一个特征,在这种情况下,必须使用extends关键字。在下面的代码示例中,我们使用 Marks trait 扩展了 Total trait。
class Example {
static void main(String[] args) {
Student st = new Student();
st.StudentID = 1;
println(st.DisplayMarks()); //Total
}
}
trait Marks {
void DisplayMarks() {
println("Marks1");
}
}
trait Total extends Marks {
void DisplayMarks() {
println("Total");
}
}
class Student implements Total {
int StudentID
}
闭包是一个短的匿名代码块。它通常跨越几行代码。一个方法甚至可以将代码块作为参数。它们是匿名的。
下面是一个简单闭包的例子,
class Example {
static void main(String[] args) {
def clos = {println "Hello World"};
clos.call();
}
}
在上面的例子中,代码行 - {println“Hello World”}被称为闭包。此标识符引用的代码块可以使用call语句执行。
运行结果 :
Hello World
闭包中的形式参数
闭包也可以包含形式参数,以使它们更有用,就像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
闭包和变量
闭包可以在定义闭包时引用变量。例
class Example {
static void main(String[] args) {
def str1 = "Hello";
def clos = {param -> println "${str1} ${param}"}
clos.call("World");
str1 = "Welcome";
clos.call("World");
}
}
在上面的例子中,除了向闭包传递参数之外,我们还定义了一个名为str1的变量。闭包也接受变量和参数。
运行结果
Hello World
Welcome World
在方法中使用闭包
闭包也可以用作方法的参数。在Groovy中,很多用于数据类型(例如列表和集合)的内置方法都有闭包作为参数类型。
以下示例显示如何将闭包作为参数发送到方法。
class Example {
def static Display(clo) {
clo.call("Inner");
}
static void main(String[] args) {
def str1 = "Hello";
def clos = { param -> println "${str1} ${param}" }
clos.call("World");
str1 = "Welcome";
clos.call("World");
Example.Display(clos);
}
}
在上述示例中:
我们定义一个名为Display的静态方法,它将闭包作为参数
然后我们在我们的main方法中定义一个闭包,并将它作为一个参数传递给我们的Display方法。
运行结果
Hello World
Welcome World
Welcome Inner
集合和字符串的闭包
几个list,Map和String方法接受一个闭包作为参数。让我们看看在这些数据类型中如何使用闭包的例子。
使用闭包和列表
以下示例显示如何使用闭包与列表。在下例中,我们首先定义一个简单的值列表。列表集合类型然后定义一个名为.each的函数。此函数将闭包作为参数,并将闭包应用于列表的每个元素
class Example {
static void main(String[] args) {
def lst = [11, 12, 13, 14];
lst.each {println it}
}
}
运行结果:
11
12
13
14
使用映射闭包
以下示例显示了如何使用闭包。在下例中,我们首先定义一个简单的关键值项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
闭包本身也提供了一些方法:
find() find方法查找集合中与某个条件匹配的第一个值
findAll() 它找到接收对象中与闭合条件匹配的所有值
any() & every() 方法any迭代集合的每个元素,检查布尔谓词是否对至少一个元素有效
collect() 该方法通过集合收集迭代,使用闭包作为变换器将每个元素转换为新值
注释是元数据的形式,其中它们提供关于不是程序本身的一部分的程序的数据。注释对它们注释的代码的操作没有直接影响。
注释使用:
编译器信息 - 编译器可以使用注释来检测错误或者抑制警告
编译时和部署时处理 - 软件工具可以处理注释信息以生成代码,XML文件等
运行时处理 - 一些注释可以在运行时检查
在Groovy中,基本注释如下所示:
@interface - @符号向编译器提示以下是注释
单行注释
//
多行注释
/* */
字符串类型
@interface Simple {
String str1() default "HelloWorld";
}
枚举类型
enum DayOfWeek { mon, tue, wed, thu, fri, sat, sun }
@interface Scheduled {
DayOfWeek dayOfWeek()
}
类 类型
@interface Simple {}
@Simple
class User {
String username
int age
}
def user = new User(username: "Joe",age:1);
println(user.age);
println(user.username);
注释成员值
使用注释时,需要至少设置所有没有默认值的成员。当定义后使用注释示例时,需要为其分配一个值。
@interface Example {
int status()
}
@Example(status = 1)
关闭注释参数
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'
}
元注释
这是groovy中注释的一个非常有用的功能。有时可能有一个方法的多个注释,如下,有时这可能变得麻烦有多个注释。
@Procedure
@Master class
MyMasterProcedure {}
在这种情况下,您可以定义一个元注释,它将多个注释集中在一起,并将元注释应用于该方法,所以对于以上的例子,可以使用AnnotationCollector来定义注释的集合。
import groovy.transform.AnnotationCollector
@Procedure
@Master
@AnnotationCollector
完成后,可以应用以下元注释器到该方法
import groovy.transform.AnnotationCollector
@Procedure
@Master
@AnnotationCollector
@MasterProcedure
class MyMasterProcedure {}
参考:Groovy 概述_w3cschool