Groovy基础以及语法

本文详细介绍了Groovy语言的一些关键特性,包括动态类型、函数定义时参数可不指定类型、函数返回值处理、区间操作(闭区间与半开区间)、GString的使用以及对Java中==操作符的扩展。此外,还提到了Groovy中的Expando类用于动态创建可拓展对象,以及可观察的List、Map和Set的使用,这些特性使得Groovy在代码简洁性和灵活性上有很大优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

语言特性

  1. Groovy 注释标记和 Java 一样,支持 // 或者 /**/
  2. Groovy 语句可以不用分号结尾。 (Groovy 为了尽量减少代码的输入,确实煞费苦心)
  3. Groovy 中支持动态类型,即定义变量的时候可以不指定其类型。 Groovy 中,变量定义可以使用关键字 def。 注意,虽然 def 不是必须的,但是为了代码清晰,建议还是使用 def 关键字
def varInstanceOfInteger = 1
def varInstanceOfString = "This line has no meanings."
def int integer1 = 2 //也可以直接指定类型

4.函数定义时参数可以不指定类型(理解成java里参数赛泛型即可)

String function(arg1,arg2){
	...
}

5.除了上面的几点外, 函数的返回值也可以是无类型的;(不过因为Groovy是基于Java并最后运行在JVM上, 这些所谓的无返回值的函数应该都是用的Object类型吧)
就比如:

def function1(){
	// (这最后一行代码即是该函数的返回值)
}
String function(){
	return "This is a string."
	//如果指定了函数的返回类型, 则可不必加def关键字来定义函数
}

6.函数返回值: Groovy的函数里, 可以不适用 return关键字. 如果不使用的话, 则函数里最后一句代码的执行结果被设置成返回值.

def function(){
	"something"//如果是最后一行,输出"something"
	1 //如果是最后一行,输出 1
	//按我目前这样的写法 1 为最后一行,所以输出1
}

如果在定义函数的时候声明了返回值类型的话, 函数中则必须使用正确的数据类型, 否则运行时会报错. 如果没声明类型即可随便返回.

7.StringGstring
那么在Java中使用的是String, 那么在兼容的groovy里当然也可以使用String, 不过groovy也提供的有Gstring供我们使用.
三个引号( ‘’’ )中的字符串更支持随意换行:

def sth = "This is Line 1"  
//这就是String的写法
----------------------------------------
def num = 1
def sth2 = "This is Line $num" 
//这种是Gstring的写法, 
//和mybatis的传值有着异曲同工之妙
---------------------------------------
def multiPart = '''
    第一行
    第二行
    第三行
    第四行...
    '''

8.Groovy中调用函数时也可以不加括号, 比如:
print() -> print / 两个效果是一样的
因为不加括号, 所以有时候Groovy经常性的会把函数和属性的调用混淆.
在这里插入图片描述
在这里插入图片描述
如图就是

9.groovy中的==

在一般情况下
java中的==表示引用相同
但是在groovy中如果对象实现了Comparable, 那么就可以通过 .compareTo()==0来表示是否相等.
如果对象没有实现Comparable, 则会用 .equals() 来进行判断;
注: 在groovy中如果要判断两个对象引用是否相等则使用 .is()

10.assert
就相当于一种trycatch或者fail-fast这种机制, 如果assert判断的代码不为true, 则直接停止运行并报错, 后面的就不会再执行, 如果为true则接着执行后面的代码.

API docs

http://docs.groovy-lang.org/docs/latest/html/api/index.html
这个是groovy的官方api文档, 有不会的类或者不明白具体实现的即可在这上面进行查找.
在这里插入图片描述

List操作

在这里插入图片描述
在这里插入图片描述
其实就还是Java里的那套东西

List迭代

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
因为许多内容与Java中的重复, 所以下面我就只说相对特殊一点的.

区间(Ranges)

Ranges定义使用 … 代表闭区间(包括起点和终点)

Ranges定义使用 …< 代表一个半开半闭,只包含第一个值不包含最后一个值。

def range = 1..10
range.size() //==10
range.get(2) //==3
range.contains(1) //==true
range instanceof java.util.List //true
//以上是闭区间
//以下是半开区间
def range 1..<10
range.size() //==9
range.get(2) //3
range.contains(10) //==false
//不用下标的方式
range.from == 1
range.to == 10

当然这样的操作在关于字母也是一样

def range = 'a'..'d'
assert range.size() //==4
assert range.size() //== 4
assert range.get(2) //== 'c'
assert range[2] //== 'c'
assert range instanceof java.util.List //==true
assert range.contains('a') //==true
assert range.contains('d') //==true
assert range.contains('e') //==false

这样便捷的操作在操作for循环也是可以的

for(i in 1..10){
	println "输出第${i}次"
}
//Groovy的风格是
(1..10).each{i ->
	println "输出第${i}次"
}

在switch语句中也可以存在, 用于判断年龄等非常好用

switch(years){
	case 10..17: println "青少年";
		break;
	case 18..60: println "成年人";
		break;
	case 61..100: println "老年人";
		break;
}

GPath支持

def listOfMaps = [
['a': 11, 'b': 12], 
['a': 21, 'b': 22]
]
assert listOfMaps.a //== [11,21]
assert listOfMaps*.a == [11, 21] 
listOfMaps = [['a': 11, ‘b': 12], [‘a': 21, 'b': 22], null]
assert listOfMaps*.a == [11, 21, null] 
assert listOfMaps*.a == listOfMaps.collect { it?.a }

*号操作

简单来说, 星号操作是允许你在一个集合的全部元素中调用某个方法或属性的简洁操作:

assert [1, 3, 5] //== ['a', 'few', 'words']*.size()
class Person {
	String name
	int age
}
def persons = [
new Person(name:'Hugo', age:17), 
new Person(name:'Sandra',age:19)
]
assert [17, 19] //== persons*.age

使用下标操作

可以使用下标来索引lists, arrays, maps.

def text = 'nice cheese gromit!'
def x = text[2]
assert x //== 'c'
assert x.class == String

def sub = text[5..10]
assert sub //== 'cheese'
def list = [10, 11, 12, 13]
def answer = list[2,3]
assert answer //== [12,13]

也可以使用区间来提取集合:

list = 100..200
sub = list[1, 3, 20..25, 33]
assert sub 
//== [101, 103, 120, 121, 122, 123, 124, 125, 133]

对于不可变的集合来说, 下标操作也可以用于更新已有集合

list = ['a','x','x','d']
list[1..2] = ['b','c']
assert list //== ['a','b','c','d']

比较令人眼前一亮的是, 在下标操作这块, 负数也是被允许的, 表示从集合后面提取元素, 比如:

text = "nice cheese gromit!"
x = text[-1]
assert x //== "!"
def name = text[-7..-2]
assert name //== “gromit”

同样的, 如果倒着使用区间(起点大于终点这种), 结果也会是反的

text = "nice cheese gromit!"
name = text[3..1]
assert name //== "eci"

Expando

Expando类可以用于动态创建可拓展对象。尽管它的类名没有采用ExpandoMetaClass。每一个Expando对象代表一个独立的动态的实例,可以在运行时被属性或方法所拓展

def expando = new Expando()
expando.name = 'John'
assert expando.name //== 'John'

一个特殊的例子是当一个动态属性注册到一个闭包代码块。一个注册就可以被方法所动态调用:

def expando = new Expando()
expando.toString = { -> 'John' }
expando.say = { String s -> "John says: ${s}" }
assert expando as String //== 'John'

assert expando.say('Hi') //== 'John says: Hi'

可观察的list,map和set

Groovy提供了可观察的lists,maps和sets。每一个都是一个 java.beans.propertyChangeEvnent事件的触发器。当元素被添加,删除,修改就会被触发。注意 PropertyChangeEvent不仅仅当某些事件发生才出发,同时可以保存新旧值。

可能会有类型改变,可观察的集合可能需要更加特别的PropertyChangeEvnet类型。比如当添加一个元素到可观察list触发一个ObservableList.ElementAddedEvent事件。

def event //(1)
def listener = {
if (it instanceof ObservableList.ElementEvent) { //(2)
	event = it
}
} as PropertyChangeListener
def observable = [1, 2, 3] as ObservableList //(3)
observable.addPropertyChangeListener(listener) //(4)

observable.add 42 //(5)

assert event instanceof ObservableList.ElementAddedEvent

def elementAddedEvent = event as ObservableList.ElementAddedEvent

assert elementAddedEvent.changeType == ObservableList.ChangeType.ADDED

assert elementAddedEvent.index == 3

assert elementAddedEvent.oldValue == null

assert elementAddedEvent.newValue == 42

(1)声明一个PropertyChangeEventListener可以捕捉触发事件

(2)ObservableList.ElementEvent和它的相关类型是相对与这个监听器

(3)注册一个监听器

(4)从给定的list创建一个ObservableList

(5)ObservableList.ElementAddedEvent事件的触发器

注意,添加一个元素将会触发两个事件,第一个是ObservableList.ElementAddedEvent 第二个是 PropertyChangeEvent,用来通知监听器这次修改属性的size
ObservableList.ElementClearedEvent 事件类型是另外一个有趣的事件。无论什么时候多个元素被删除,比如当我们调用clear()方法的时候,它将会保存被删除的元素

def event
def listener = {
if (it instanceof ObservableList.ElementEvent) {
	event = it
}
} as PropertyChangeListener
def observable = [1, 2, 3] as ObservableListobservable.addPropertyChangeListener(listener)

observable.clear()

assert event instanceof ObservableList.ElementClearedEvent

def elementClearedEvent = event as ObservableList.ElementClearedEvent

assert elementClearedEvent.values //== [1, 2, 3]

assert observable.size() //== 0

在这块ObservableMapObservableSet是相似的同一个概念,和ObservableList一样.
那么以上就是Groovy的基础以及部分语法.
如果想要有更好的理解, 建议翻阅官方的api文档, 或者在开源社区https://www.open-open.com/lib/view/open1444055981994.html#articleHeader4查阅也可以, 我本人就参考了许多.
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

OGtwelve

不用打赏, 各位学的会是关键.

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

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

打赏作者

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

抵扣说明:

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

余额充值