这里对Groovy中常见的操作符进行介绍
操作符用法 算术操作符 同Java一样,在算术操作符方面Groovy并无二致。示例代码如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 class OperatorDemo { static void arithmetic() { assert 3 +4 == 7 def foo1 = 3 foo1 += 4 assert foo1 == 7 assert 4 -3 == 1 def foo2 = 4 foo2 -= 3 assert foo2 == 1 assert 4 *3 == 12 def foo3 = 4 foo3 *=3 assert foo3 == 12 assert 12 /3 == 4 def foo4 = 12 foo4 /= 3 assert foo4 ==4 assert 13 %3 == 1 def foo5 = 13 foo5 %= 3 assert foo5 == 1 assert 2 **3 == 8 def foo6 = 2 foo6 **= 3 assert foo6 == 8 assert +3 == 3 assert -4 == 0 -4 assert -(-11 ) == 11 def a1 = 2 def b1 = a1++ assert a1 == 3 assert b1 == 2 def a2 = 2 def b2 = ++a2 assert a2 == 3 assert b2 == 3 def a3 = 2 def b3 = a3-- assert a3 == 1 assert b3 == 2 def a4 = 2 def b4 = --a4 assert a4 == 1 assert b4 == 1 } }
关系运算符 Groovy的关系运算符示例如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class OperatorDemo { static void relational() { assert (3 *4 ) == (10 +2 ) assert 3 != 4 assert 3 < 4 assert 3 <=4 assert 4 <=4 assert 5 > 4 assert 5 >=4 assert 5 >=5 } }
逻辑运算符 Groovy在逻辑运算符支持常见的与、或、非,同时具备短路求值的特点
1 2 3 4 5 6 7 8 9 10 11 12 class OperatorDemo { static void logical() { assert true && true assert false || true assert !false } }
位运算 Groovy与Java一样,同样支持位运算。示例如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class OperatorDemo { static void bit() { int a = 0b1010 assert a == 10 int b = 0b0110 assert b == 6 int c = 0b0010 assert c ==2 assert (a&b) == c int d = 0b1110 assert d == 14 assert (a|b) == d int e = 0b1100 assert e == 12 assert (a^b) == e byte f = 0b00001111 assert f == 15 byte h = 0b11110000 assert h == -16 assert (~f) == h byte i = 0b00000011 assert i == 3 byte j = 0b00001100 assert j == 12 assert (i<<2 ) == j assert (j>>2 ) == i byte k = 0b11111011 assert k == -5 byte p = 0b11111110 assert p == -2 assert (k>>2 ) == p int q = 0x8022 _11ff assert q == -2145250817 int r = 0x0080 _2211 assert r == 8397329 assert (q>>>8 ) == r } }
条件运算符 Groovy不仅提供了传统的三元运算符。还特别提供了Elvis运算符、Elvis赋值运算符。对于前者而言,如果Elvis运算符左边的操作数判定为真,则返回左边操作数; 否则返回右边的操作数;对于后者而言,Elvis赋值运算符, 其是对Elvis运算符的进一步简化, 省去了再次赋值操作。示例如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 class OperatorDemo { static void conditional() { def a1 = (2 >1 ) ? 3 : 4 assert a1 == 3 def a2 = (2 >3 ) ? 3 : 4 assert a2 == 4 def b1 = "Hello World" b1 = b1 ?: "Hi" assert b1 == "Hello World" def b2 = "" b2 = b2 ?: "Hi" assert b2 == "Hi" def c1 = "Hello World" c1 ?= "Hi" assert c1 == "Hello World" def c2 = "" c2 ?= "Hi" assert c2 == "Hi" } }
正则操作符 特别地,Groovy针对正则操作提供了相应的操作符。示例如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class OperatorDemo { static void regular() { String regex = /\S+\s+\S+/ def pattern1 = ~regex assert pattern1 instanceof Pattern def text1 = "One Two Three Four Five" def matcher1 = pattern1.matcher(text1) assert matcher1 instanceof Matcher assert matcher1.size() == 2 assert matcher1[0 ] == "One Two" assert matcher1[1 ] == "Three Four" def matcher2 = (text1 =~ regex) assert matcher2 instanceof Matcher assert matcher2.size() == 2 assert matcher2[0 ] == "One Two" assert matcher2[1 ] == "Three Four" boolean b1 = "One Two Three Four" ==~ regex boolean b2 = "One Two" ==~ regex assert b1 == false assert b2 == true } }
对象操作符 Groovy对于对象引用提供了丰富的操作符。需要特别提醒的是,在Java中对两个对象引用使用==操作符比较的是两个对象的地址是否一样;而在Groovy中==操作符用于比较两个对象的内容是否一样,事实上该操作符是通过equals方法实现的。当然Groovy自然也是支持比较两个对象的地址,其提供了===操作符。事实上该操作符是通过is方法实现的。示例代码如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 class OperatorDemo { static void object () { def person1 = new Person ("remark" : "领军人才" ) person1.name = "Aaron" assert person1.name == "Aaron" person1.age = 18 assert person1.age == 218 assert person1.remark == "<REMARK INFO>: 领军人才" assert person1.@remark == "领军人才" person1.@age = 17 assert person1.age == 17 Person person2 = null assert person2?.getAge() == null assert person1?.getAge() == 17 MethodClosure fun1 = person1.&getAge assert fun1 instanceof Closure assert fun1 () == 17 assert fun1.call() == 17 def fun3 = person1.&test1 assert fun3.call("Bye" ) == "Aaron: Bye" assert fun3.call(3 ) == "<17 + 3> -->> 20" def fun4 = Person.&new Person person3 = fun4.call("name" :"Bob" ) assert person3.name == "Bob" def fun2 = String.&toUpperCase assert fun2.call("Hello" ) == "HELLO" def fun5 = Person.&test1 assert fun5.call( person1, "welcome" ) == "Aaron: welcome" def fun6 = String.&valueOf assert fun6.call( false ) == "false" assert fun6.call( 996 ) == "996" def list1 = ["71" ,"2" ,"4" ].stream() .map( Integer::valueOf ) .collect( Collectors.toList() ) assert list1 == [71 ,2 ,4 ] def list1a = [1 ,2 ] as LinkedList def list1b = list1a def list2 = [1 ,2 ] as LinkedList assert list1a == list2 assert list1a.equals( list2 ) assert list1a != [985 ,211 ] assert !( list1a.equals([985 ,211 ]) ) assert list1a === list1a assert list1a.is(list1b) assert list1a !== list2 assert !( list1a.is(list2) ) } } class Person { String name Integer age String remark void setAge (Integer age) { this .age = 200 + age } String getRemark () { return "<REMARK INFO>: $remark" } @Override boolean equals (Object other) { if (!other || !(other instanceof Person) || name != other.name || age != other.age || remark != other.remark ) { return false } return true } String test1 (String msg) { return "$name: $msg" } String test1 (Integer num) { return "<${this.age} + ${num}> -->> ${this.age+num}" } }
其它 Groovy中其它部分常见的操作符,示例如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 class OperatorDemo { static void other () { assert (15 <=> 15 ) == 0 assert (44 <=> 22 ) == 1 assert (22 <=> 44 ) == -1 String[] array1 = ["Amy" , "Aaron" ] array1?[1 ] = "Bob" assert array1?[0 ] == "Amy" assert array1?[1 ] == "Bob" array1 = null assert array1?[0 ] == null def map1 = [:] map1?["Aaron" ] = 18 assert map1?["Aaron" ] == 18 map1 = null assert map1?["Aaron" ] == null def list1 = ["MicroSoft" , "Apple" , "Xiaomi" , "FaceBook" ] assert "Apple" in list1 assert list1.isCase( "Apple" ) assert !("Huawei" in list1) assert 996 in Integer assert Integer.isCase(996 ) assert !(3.14f in Integer) assert 3.14f in Float assert Float.isCase( 3.1f ) } }
操作符重载 在Groovy中,部分操作符是有对应的方法。换言之,通过操作符或方法调用在本质上效果是一致的。但操作符一旦有对应的方法,就为我们提供了另外一种编程方式,即进行操作符的重载。在特殊场景下,操作符的重载可以大大方便我们的使用。比如期望通过乘法符号计算两个矩阵的乘积,在Java中这显然是不可能。因为我们不能自定义乘法操作符的具体逻辑,而在Groovy中则可以在我们自定义的矩阵类中通过重载乘法操作符实现。这里给出Groovy可以进行重载的操作符及对应的方法名
下面给出一个进行重载操作符的示例,方便理解、使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 class OperatorOverLoad { static void main(String[] args){ testPlus() testNext() testCall() } static void testNext() { Food food1 = new Food("西瓜" , 14 ) food1++ assert food1.toString() == "Food { type=西瓜, num=15 }" def food2 = new Food(type: "哈蜜瓜" ) food2++ assert food2.toString() == "Food { type=哈蜜瓜, num=1 }" } static void testPlus() { Food food1 = new Food("橘子" , 1 ) Food food2 = new Food("橘子" , 2 ) Food food3 = new Food("type" : "橘子" ) Food food4 = new Food("type" : "苹果" ) assert (food1 + food2).toString() == "Food { type=橘子, num=3 }" assert (food2 + food3).toString() == "Food { type=橘子, num=2 }" assert (food1 + food4) == null } static void testCall() { Food food1 = new Food("柠檬" , 21 ) def str = food1() assert food1.call() == "Food { type=柠檬, num=21 }" assert food1() == "Food { type=柠檬, num=21 }" } } class Food { String type Integer num Food(String type, Integer num) { this .type = type this .num = num } Food() { } Food plus(Food other) { if ( !this .type || this .type != other?.type ) { return null } Integer num1 = this.num ?: 0 Integer num2 = other.num ?: 0 Integer result = num1 + num2 return new Food("type" :type, "num" : result) } Food next() { this .num ?= 0 this.num++ return this } String call() { return toString() } @Override String toString() { return "Food { type=$type, num=$num }" } }
参考文献
Groovy In Action · 2nd Edition Dierk König、Guillaume Laforge著