当前位置:   article > 正文

Groovy 运算符

groovy三元运算符

Groovy 运算符

官方文档(运算符):http://www.groovy-lang.org/operators.html

1. 算术运算符

1.1 除法

如果操作数是float或double,则除法//=会产生一个double,反之,则会产生一个BigDecimal的结果(当这两个操作数都是整型short, char, byte, int, long, BigInteger 或 BigDecimal的组合)。

对于像Java那样的整数除法,应该使用intdiv()方法,Groovy并没有提供一个专用的整数除法运算符。

1.2 次方运算符

**

  1. assert 2 ** 3 == 8
  2. def f = 3
  3. f **= 2
  4. assert f == 9

2. 条件运算符

2.1 三元运算符

Java写法:

result = (string!=null && string.length()>0) ? 'Found' : 'Not found'

Groovy的更简短:

result = string ? 'Found' : 'Not found'

Groovy truth

2.2 Elvis operator

Elvis运算符 ?:是三元运算符的缩短:

  1. displayName = user.name ? user.name : 'Anonymous'
  2. displayName = user.name ?: 'Anonymous'

使用Elvis操作符可以减少代码的冗余,减少重构时出错的风险,消除条件和正返回值的复制。

3. 对象操作符

3.1 安全导航操作符

安全导航操作符?.用于避免NullPointerException,通常使用对象引用时,在访问对象的方法或属性之前,可能需要验证引用是否为null,为了避免这种情况,安全导航操作符将简单地返回null而不是抛出异常(如果为引用为null,则返回null)。

  1. class Person{
  2. public String name = 'aaa'
  3. }
  4. Person person
  5. println(person?.name) // null
  6. println(person.name) // java.lang.NullPointerException

3.2 直接字段访问操作符

因为Groovy自动支持属性的getter方法,但有时我们会自定义getter方法,如果不想调用自定义的getter方法,那么可以用直接字段访问操作符 .@

  1. class User {
  2. public final String name
  3. User(String name) { this.name = name}
  4. String getName() { "Name: $name" }
  5. }
  6. def user = new User('Bob')
  7. assert user.name == 'Name: Bob' // 会触发getter方法调用
  8. assert user.@name == "Bob" // 直接访问name字段

.@会强制使用字段而不是getter

3.3 方法指针操作符

方法指针操作符 .& 将对方法的引用存储于变量中,以便稍后调用它:

  1. def str = 'example String'
  2. def upperFun = str.&toUpperCase //将str实例的toUpperCase方法的引用存储到upperFun变量内
  3. def result = upperFun() // 像常规方法一样调用upperFun
  4. assert result == str.toUpperCase() // 与在str上直接调用方法的结果一样
  5. println(result) // EXAMPLE STRING

使用方法指针有多个优点。首先,方法指针的类型是 groovy.lang.Closure,所以可以在任何使用闭包的地方使用它。特别适合于针对策略模式的需求转换现有方法的情景:

  1. class Person{
  2. String name
  3. int age
  4. Person(String name, int age){
  5. this.name = name
  6. this.age = age
  7. }
  8. }
  9. def list = [
  10. new Person("wzx", 24),
  11. new Person("lc", 22)]
  12. //描述一个Person对象的方法
  13. def describe(Person p){
  14. "$p.name is $p.age"
  15. }
  16. //转换方法:遍历List,将每一个元素都执行一次describe方法
  17. def transform(List elements, Closure closure){
  18. def list = [];
  19. elements.each{
  20. list << closure(it)
  21. }
  22. list
  23. }
  24. //存储describe方法引用的变量
  25. def describeReference = this.&describe
  26. assert transform(list, describeReference) == ['wzx is 24', 'lc is 22']

存储引用的变量只与方法名称绑定,其参数在运行时才会解析。这意味着如果有多个名称相同的方法,在运行时才会根据传入的参数调用适当的方法:

  1. def doSomething(String str){str.toUpperCase()}
  2. def doSomething(int num){num ** 2}
  3. def reference = this.&doSomething
  4. assert reference('abc') == 'ABC'
  5. assert reference(3) == 9

4. 正则表达式操作符

4.1 Pattern操作符

Pattern操作符 ~ 提供了一个创建java.util.regex.Pattern实例的简单方式,通常和斜线字符串一起使用,不过可以与任何Groovy String一起使用。

  1. def p = ~/foo/
  2. p = ~'foo'
  3. p = ~"foo"
  4. p = ~$/dollar/slashy $ string/$
  5. p = ~"${pattern}"
  6. assert p instanceof Pattern

创建Pattern后不能再改变

  1. def pattern = 'aabb'
  2. def p = ~"${pattern}"
  3. assert p.toString() == 'aabb'
  4. pattern = 'ttyy'
  5. assert p.toString() == 'aabb'

4.2 查找操作符

可以使用 =~ 操作符直接构建一个java.util.regex.Matcher实例

  1. def text = "some text to match"
  2. def m = text =~ /.*match.*/
  3. assert m instanceof Matcher // =~ 的返回类型为Matcher
  4. assert m // true,相当于调用了m.find()
  5. println(m.group()) // some text to match

4.3 匹配操作符

==~ 返回的是Boolean

  1. def text = 'text to match'
  2. def m = text ==~ /.*match.*/
  3. assert m instanceof Boolean
  4. if (m) {
  5. println('text match!') // text match!
  6. }

5. 其他操作符

5.1 扩展操作符

*. 用于对聚合对象的所有item进行操作,相当于在每一个item上操作,并将结果放在一个List中

  1. class Person{
  2. String name
  3. int age
  4. }
  5. def persons = [
  6. new Person(name:'wzx', age:24),
  7. new Person(name:'lc', age:22)
  8. ]
  9. def result = persons*.name; //相当于在每一个item上操作,并将结果放在一个List中
  10. assert result instanceof List
  11. println(result) // [wzx, lc]

扩展运算符是null安全的,如果集合的一个元素为null,它将返回null而不是抛出NullPointerException

  1. def persons = [
  2. new Person(name:'wzx', age:24),
  3. null,
  4. new Person(name:'lc', age:22)
  5. ]
  6. def result = persons*.name;
  7. println(result) // [wzx, null, lc]

对于实现了Iterable接口的任意类,都可以使用该操作符

5.1.1 扩展方法参数

* 例如,假设具有以下方法签名:

  1. def fun(String a, String b, int c){
  2. "$a $b $c"
  3. }

有以下列表:

def args = ["aaa", "bbb", 123]

可以调用该方法而不必定义中间变量:

assert function(*args) == 'aaa bbb 123'

甚至可以将普通参数与传播参数进行混合:

  1. params = ["aaa", "bbb"]
  2. assert function(*args, 123) == 'aaa bbb 123'
5.1.2 扩展List元素

*

  1. def items = [4,5]
  2. def list = [1,2,3,*items,6] //不用addAll()而直接将items插入到list中
  3. assert list == [1,2,3,4,5,6] //items已经被内联到list中
5.1.3 扩展Map元素

*:

  1. def m1 = [c:3, d:4]
  2. def map = [a:1, b:2, *:m1]
  3. assert map == [a:1, b:2, c:3, d:4]

扩展的结果与插入操作符的位置有关:

  1. def m1 = [c:3, d:4]
  2. def map = [a:1, b:2, *:m1, d:8] // 扩展后d的值被重新指定了
  3. assert map == [a:1, b:2, c:3, d:8]

5.2 范围操作符

Groovy提供..来创建范围对象

  1. def range = 0..5 //用一个变量来存储一个整数范围对象
  2. assert (0..5).collect() == [0, 1, 2, 3, 4, 5] // 一个IntRange,包含边界
  3. assert (0..<5).collect() == [0, 1, 2, 3, 4] // 一个IntRange,不包含上边界
  4. assert (0..5) instanceof List // groovy.lang.Range实际是一个List
  5. assert (0..5).size() == 6 //可以调用size()
  6. assert ('a'..'d').collect() == ['a','b','c','d']

5.3 比较运算符

<=>代理了compareTo方法:

  1. assert (1 <=> 1) == 0
  2. assert (1 <=> 2) == -1
  3. assert (2 <=> 1) == 1
  4. assert ('a' <=> 'z') == -1

5.4 下标运算符

下标运算符[]是getAt或putAt的简写:

  1. def list = [0,1,2,3,4]
  2. list[2] = 4
  3. assert list[0..2] == [0,1,4]
  4. list[0..2] = [6,6,6]
  5. assert list == [6,6,6,3,4]

下标运算符结合自定义实现的getAt/ putAt是解构对象的一种方便的方法:

  1. class Person{
  2. int id;
  3. String name;
  4. def getAt(int i){ //自定义的getAt实现
  5. switch(i){
  6. case 0: return id;
  7. case 1: return name;
  8. }
  9. throw new IllegalArgumentException("No such element $i")
  10. }
  11. void putAt(int i, def value){ //自定义的putAt实现
  12. switch(i){
  13. case 0: this.id = value; return;
  14. case 1: this.name = value; return;
  15. }
  16. throw new IllegalArgumentException("No such element $i")
  17. }
  18. }
  19. def p = new Person(id:10001, name:"wzx")
  20. assert p[0] == 10001;
  21. assert p[1] == "wzx"
  22. p[1] = "lc"
  23. assert p[1] == "lc"
  24. assert p.name == "lc"

5.5 从属运算符

in相当于调用 isCase

  1. def list = ['wzx', 'lc', 'aaa']
  2. assert ('lc' in list)
  3. assert list.contains('lc')
  4. assert list.isCase('lc')
  5. def map = ['wzx':24, 'lc':22]
  6. assert ('wzx' in map)
  7. assert map.containsKey('wzx')
  8. assert map.isCase('wzx')

5.6 相等运算符

在Groovy中,使用==测试相等性不同于在Java中使用相同的运算符。在Groovy,它会调用equals。如果要比较引用的相等性,应该使用is

  1. def list1 = ['wzx', 'lc']
  2. def list2 = ['wzx', 'lc']
  3. assert list1 == list2
  4. assert !list1.is(list2)

5.7 强制转换操作符

类型不兼容:

  1. String s = "123"
  2. Integer x = (Integer) s

运行时抛出异常:GroovyCastException: Cannot cast object '123' with class 'java.lang.String' to class 'java.lang.Integer'

可以使用as完成转换:

  1. String s = "123"
  2. Integer x = s as Integer
  3. println(x) // 123

当一个对象被强转到另一个对象时,若目标类型与源类型相同,强转将返回一个新对象。转换的规则取决于源类型和目标类型,如果没有找到转换规则,强转可能会失败。通过asType方法可以自定义转换规则:

  1. class Orange{
  2. String name
  3. }
  4. class Apple{
  5. String name
  6. def asType(Class target){
  7. if(target == Orange){
  8. return new Orange(name:name)
  9. }
  10. throw new ClassCastException("Apple cannot be coerced into $target")
  11. }
  12. }
  13. def apple = new Apple(name: "Apple")
  14. def orange = apple as Orange //强转成功则返回一个新对象
  15. assert !(orange instanceof Apple)
  16. assert orange instanceof Orange
  17. println(orange.name); //Apple

5.8 调用操作符

操作符()是call的隐式调用,对于定义了call方法的任何对象都可以省略.call部分

  1. class MyCallable {
  2. int call(int x) {
  3. 2*x
  4. }
  5. }
  6. def mc = new MyCallable()
  7. assert mc.call(2) == 4
  8. assert mc(2) == 4

6. 运算符优先级

7. 运算符重载

Groovy允许重载各种运算符,以便它们可以与自己的类一起使用,下面是个简单的类:

  1. class Bucket {
  2. int size
  3. Bucket(int size) { this.size = size }
  4. Bucket plus(Bucket other) {
  5. return new Bucket(this.size + other.size)
  6. }
  7. }

Bucket 实现了一个特殊的方法 plus(),只要实现该方法,Bucket类就可以与+运算符一起使用:

  1. def b1 = new Bucket(4)
  2. def b2 = new Bucket(11)
  3. assert (b1 + b2).size == 15

所有Groovy运算符(非比较)都有一个相应的方法,可以在自己的类中实现。唯一的要求是方法是public,有正确的名称,正确的参数数量,参数类型取决于要运算符右侧要支持的类型,比如:

  1. Bucket plus(int capacity) {
  2. return new Bucket(this.size + capacity)
  3. }
  4. assert (b1 + 11).size == 15

以下是运算符及其相应方法的完整列表:

1205520-20170820232111615-341804996.png

转载于:https://www.cnblogs.com/zhaoxia0815/p/7391502.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/810387
推荐阅读
相关标签
  

闽ICP备14008679号