更多代码相关的内容可以参考:https://github.com/zclhit/groovy_learning/tree/main
groovy在语言层面支持一套数据类型,提供了直接声明和特定的操作符,包括字符、正则和数字类型。也包括范围、列表和映射等。
我将会在这里使用groovy所有的简单类型和集合类型
Java中的专有类型:int/double/char/byte/long 等
Java中的引用类型:Object/String 等
在java中不能创建自定义的值类型。
而引用类型指向了一个具体的对象,Java不能在专有类型上进行方法调用,也不能向对Object一样操作专用类型,容器只能接受专有类型的包装类,
比如ArrayList
是合法的,但是ArrayList
就是不合法的。
对于一个功能,Java实现是:
class Add{
Integer first = list.get(0);
Integer second = list.get(1);
int sum = first.intValue() + second.intValue();
List<Integer> result = new ArrayList<>();
result.add(sum);
}
而到了groovy,就只需要一行代码:
results.add(first + second)
除此之外groovy还支持自己实现操作符
java中有特定的专有类型和包装类型,但是groovy中都是对包装类型对象的引用。
使用groovy调用java的时候,可以自动进行拆箱和装箱操作。
groovy在执行"1+1"的时候,直接使用的是Integer的plus方法,相当于1.plus(1),生成了一个值为2的新对象
对象声明的一些方式
// 隐式声明
def a = 1
def b = 1.0f
// 使用java专有类型声明
int c = 1
float d = 1
// 使用引用类型声明
Integer e = 1
String f = 'str'
但是Groovy不会允许把一个确定类型的对象当成另一个类型的对象,比如’1’就不能是Integer
为了达到某个目的,在面向对象的语言中,子类型对父类型进行的方法重写。
重写操作符实战:
class Money {
private int amount
private String currency
Money (amountValue, currencyValue) {
amount = amountValue
currency = currencyValue
}
boolean equals (Object other) {
if (null == other) return false
if (! (other instanceof Money)) return false
if (currency != other.currency) return false
if (amount != other.amount) return false
return true
}
int hashCode() {
amount.hashCode() + currency.hashCode()
}
Money plus (Money other) {
if (null == other) reutrn null
if (other.currency != currency) {
throw new IllegalArgumentException("can not add different currency")
}
return new Money(amount + other.amount, currency)
}
}
def buck = new Money(1, 'USD')
assert buck
assert buck == new Money(1, 'USD')
assert buck + buck == new Money(2, 'USD')
1+1.5
返回的是Integer, 1.5+1
返回的是BigDecimal
Groovy为处理字符串提供了很多便捷的特性,有两种处理风格:1.GString嚯java.lang.String的实例
GString可以接收占位符并且在运行时对占位符进行解析和计算。
有几种表现形式:
'str'
单引号,不会使用GString来处理,等价于java字符串"str"
双引号,和单引号等价,如果没有$转义符,就会被加工成GString'''str'''
三引号,类似于Ruby中的HERE-document/
标识字符串,不会转义反斜杠\
,适用于正则表达式的定义Groovy提供了使用的to*方法,比如toInteger,toLong,toFloat和toDouble
GString可以根据需要自动转换为java.lang.String
me = 'Tarzan'
you = 'Jane'
line = "me $me - you $you"
assert line == 'me Tarzan - you Jane'
date = new Date(0)
out = "Year $date.year Month $date.month Day $date.date"
assert out == 'Year 70 Month 0 Day 1'
out = "Date is ${date.toGMTString()} !"
assert out == 'Date is 1 Jan 1970 00:00:00 GMT !'
sql = """
SELECT FROM MyTable
WHERE Year = $date.year
"""
assert sql == """
SELECT FROM MyTable
WHERE Year = 70
"""
out = "my 0.02\$"
assert out == 'my 0.02$'
Gstring中,通过$
符号去进行变量引用,并使用它的方法或者属性值
使用${}
进行完整的闭包运算
可以直接在groovy中使用StringBuffer完成对于字符串的操作需求
greeting = 'Hello'
greeting <<= ' Groovy'
assert greeting instanceof java.lang.StringBuffer
greeting <<= '!'
assert greeting.toString() == 'Hello Groovy!'
greeting[1..4] = 'i'
assert greeting.toString() == 'Hi Groovy!'
正则表达式可以通过一个模式而不是编程来对字符串进行匹配,并且groovy为其提供了便利性的三个操作符:
myFairString = 'The rain in Spain stays mainly in the plain!'
BOUNDS = /\b/
rhyme = /$BOUNDS\w*ain$BOUNDS/
found = ''
myFairString.eachMatch(rhyme) {match ->
found += match[0] + ' '
}
assert found == 'r S p '
found = ''
(myFairString =~ rhyme).each { match ->
found += match + ' '
}
assert found == 'rain Spain plain '
cloze = myFairString.replaceAll(rhyme){it-'ain' + '___'}
assert cloze == 'The r___ in Sp___ stays mainly in the pl___!'
正则匹配结果,并进行替换。更多有关模式匹配细节相关的操作,可以参考:java.util.regex.Matcher
性能测试相关代码:
twister = 'she sells sea shells at the sea shore of seychelles'
regex = /\b(\w)\w*\1\b/
start = System.currentTimeMillis()
100000.times {
twister =~ regex
// 识别10w次
}
first = System.currentTimeMillis() - start
start = System.currentTimeMillis()
pattern = ~regex
100000.times {
pattern.matcher(twister)
}
second = System.currentTimeMillis() - start
assert first > second * 1.20
注意=~
和 = ~
的区别,通过定义模式,可以显著提升匹配速度
掌握正则表达式有助于提升我们对于字符串的处理速度
运算符,对于+ - *来说
整数除法可以通过intdiv方法来进行
提供了times,upto,downto和step方法
比如:
def store = ''
10.times {
store += 'x'
}
assert store == 'xxxxxxxxxx'
store = ''
1.upto(5) {
number -> store += number
}
assert store == '12345'
store = ''
2.downto(-2) {
number -> store += number + ' '
}
assert store == '2 1 0 -1 -2 '
store = ''
0.step(0.5, 0.1) {
number -> store += number + ' '
}
assert store == '0 0.1 0.2 0.3 0.4 '