赞
踩
目录
- #乘方
- assert 2 ** 3 == 8
-
- #非运算
- assert (!true) == false
- assert (!'foo') == false
- assert (!'') == true
-
- #三元表达式
- result = (string!=null && string.length()>0) ? 'Found' : 'Not found'
- result = string ? 'Found' : 'Not found'
-
- #艾维斯运算符
- displayName = user.name ? user.name : 'Anonymous'
- #进一步简写为:
- displayName = user.name ?: 'Anonymous'
-
避免抛出NullPointerException
这个异常。
- def person = Person.find { it.id == 123 }
- def name = person?.name
- assert name == null
接字段访问 .@
可以跳过 getXXX
方法,直接获得字段的值
assert user.@name == 'Bob'
方法指针 (.&)
操作符可以获取一个方法指针,后面再调用这个指针
- def str = 'example of method reference'
- def fun = str.&toUpperCase
- def upper = fun()
方法指针获得的值是一个groovy.lang.Closure
类型,因此可以用到任何需要闭包的地方,非常适合策略模式
- def transform(List elements, Closure action) {
- def result = []
- elements.each {
- result << action(it)
- }
- result
- }
- String describe(Person p) {
- "$p.name is $p.age"
- }
- def action = this.&describe
- def list = [
- new Person(name: 'Bob', age: 42),
- new Person(name: 'Julia', age: 35)]
- assert transform(list, action) == ['Bob is 42', 'Julia is 35']
Groovy 允许重载多个同名方法,如果方法指针指向重载同名方法,则根据参数类型来判断调用哪个方法
- def doSomething(String str) { str.toUpperCase() }
- def doSomething(Integer x) { 2*x }
- def reference = this.&doSomething
- assert reference('foo') == 'FOO'
- assert reference(123) == 246
模式运算符、匹配对象操作符、直接匹配操作符
略。
扩展操作符的本质是迭代调用并生成列表,因此任何实现了 Iterable 接口的对象都可以使用扩展操作符
- class Component {
- Long id
- String name
- }
-
- class CompositeObject implements Iterable<Component> {
- def components = [
- new Component(id: 1, name: 'Foo'),
- new Component(id: 2, name: 'Bar')]
-
- @Override
- Iterator<Component> iterator() {
- components.iterator()
- }
- }
-
- def composite = new CompositeObject()
-
- assert composite*.id == [1,2]
- assert composite*.name == ['Foo','Bar']
- 1.解包方法参数
- 下面这个方法需要三个参数
- int function(int x, int y, int z) {
- x*y+z
- }
-
- 下面这个列表有三个元素
- def args = [4,5,6]
-
- 将列表解包为三个参数传给方法
- assert function(*args) == 26
-
- 位置可以随意
- args = [4]
- assert function(*args,5,6) == 26
-
- 2.解包列表元素
- def items = [4,5]
- def list = [1,2,3,*items,6]
- assert list == [1,2,3,4,5,6]
-
- 3.解包键值对
- def m1 = [c:3, d:4]
- def map = [a:1, b:2, *:m1]
- assert map == [a:1, b:2, c:3, d:4]
-
- 如果出现重复的的键,后面的值将替换前面的值
- def m1 = [c:3, d:4]
- def map = [a:1, b:2, *:m1, d: 8]
- assert map == [a:1, b:2, c:3, d:8]
范围操作符 (..)
创建一个 groovy.lang.Range
对象,这个类型同时实现了 List
接口
- def range = 0..5
- assert (0..5).collect() == [0, 1, 2, 3, 4, 5]
- assert (0..<5).collect() == [0, 1, 2, 3, 4]
- assert (0..5) instanceof List
- assert (0..5).size() == 6
Range
对象是轻量级的,仅仅存储了上下边界,因此要创建 Range
还必须实现 Comparable
接口中的 next()
方法和 previous()
方法。因为字符对象实现了这两个方法,因此可以向下面这样用
assert('a'..'d').collect()==['a','b','c','d']
比较操作符 (<=>)
其实就是 compareTo
方法
- assert (1 <=> 1) == 0
- assert (1 <=> 2) == -1
- assert (2 <=> 1) == 1
- assert ('a' <=> 'z') == -1
索引操作符本质上是调用 getAt
和 putAt
方法,可以切片获取或者切片赋值
- def list = [0,1,2,3,4]
- assert list[2] == 2
- list[2] = 4
- assert list[0..2] == [0,1,4]
- list[0..2] = [6,6,6]
- assert list == [6,6,6,3,4]
可以重写 getAt/putAt
方法,实现一些自定义的行为
- class User {
- Long id
- String name
- def getAt(int i) {
- switch (i) {
- case 0: return id
- case 1: return name
- }
- throw new IllegalArgumentException("No such element $i")
- }
- void putAt(int i, def value) {
- switch (i) {
- case 0: id = value; return
- case 1: name = value; return
- }
- throw new IllegalArgumentException("No such element $i")
- }
- }
- def user = new User(id: 1, name: 'Alex')
- assert user[0] == 1
- assert user[1] == 'Alex'
- user[1] = 'Bob'
- assert user.name == 'Bob'
成员操作符 (in)
相当于调用了列表的 contains
方法或者 isCase
方法
- def list = ['Grace','Rob','Emmy']
- assert ('Emmy' in list)
calling list.contains('Emmy')
和 list.isCase('Emmy')
是同样的功能
==
和is操作符在 Groovy 中, ==
仅仅检测值是否相同,如果想检测是否是同一个对象,使用 is
操作符
- def list1 = ['Groovy 1.8','Groovy 2.0','Groovy 2.3']
- def list2 = ['Groovy 1.8','Groovy 2.0','Groovy 2.3']
- assert list1 == list2
- assert !list1.is(list2)
- 转型操作符 (as) 可以转换一些不兼容变量的类型,例如下面的转换会抛出异常
- Integer x = 123
- String s = (String) x
-
- 用转型操作符可以正确转换
- Integer x = 123
- String s = x as String
-
- 转型的本质实际上是调用了对象的 asType 方法,可以重写这个方法实现一些自定义的行为
- class Identifiable {
- String name
- }
- class User {
- Long id
- String name
- def asType(Class target) {
- if (target==Identifiable) {
- return new Identifiable(name: name)
- }
- throw new ClassCastException("User cannot be coerced into $target")
- }
- }
- def u = new User(name: 'Xavier')
- def p = u as Identifiable
- assert p instanceof Identifiable
- assert !(p instanceof User)
钻石操作符 (<>)
仅仅是为了兼容 Java 7 中的泛型,目前在 Groovy 中还没有什么用处。
List<String> strings = new LinkedList<>()
调用操作符 ()
隐式调用 call
方法。可以重写 call
实现一些自定义的行为,然后用调用操作符调用
- class MyCallable {
- int call(int x) {
- 2*x
- }
- }
-
- def mc = new MyCallable()
- assert mc.call(2) == 4
- assert mc(2) == 4
略。参见:http://groovy-lang.org/operators.html#Operator%20precedence
类似于c++的操作符重载,Groovy 中的大部分操作符都可以重新定义,例如:
- class Bucket {
- int size
-
- Bucket(int size) { this.size = size }
-
- Bucket plus(Bucket other) {
- return new Bucket(this.size + other.size)
- }
- }
-
- #方法 plus() 重载了 + 操作符
- def b1 = new Bucket(4)
- def b2 = new Bucket(11)
- assert (b1 + b2).size == 15
下表是各个操作符的函数名称:
操作符 | 方法 | 操作符 | 方法 |
---|---|---|---|
+ | a.plus(b) | a[b] | a.getAt(b) |
- | a.minus(b) | a[b] = c | a.putAt(b, c) |
* | a.multiply(b) | a in b | b.isCase(a) |
/ | a.div(b) | << | a.leftShift(b) |
% | a.mod(b) | >> | a.rightShift(b) |
** | a.power(b) | >>> | a.rightShiftUnsigned(b) |
| a.or(b) |
| a.next() |
& | a.and(b) | -- | a.previous() |
^ | a.xor(b) | +a | a.positive() |
as | a.asType(b) | -a | a.negative() |
a() | a.call() | ~a | a.bitwiseNegative() |
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。