Groovy运算符

官方文档

与Java一样的就不展开了~

除号(/)的特殊行为

Groovy中的除/和Java的表现不一样:

  • 当两个操作数中有一个是floatdouble时,结果是double
  • 当两个操作数都是整型(shortcharbyteintlongBigInteger)或者BigDecimal时,结果是BigDecimal
  • 如果要像Java那样取整,需要调用intdiv方法
def result = 1 / 3.0f // 当其中有一个是float或double时
println result.class  // 结果是:class java.lang.Double
println result        // 0.3333333333333333
println 4.intdiv(3)   // 结果为1,与Java一样

def newResult = 1 / 2   // 当两个操作数都是整型
println newResult.class // class java.math.BigDecimal
println newResult       // 结果是0.5

指数运算符(Power operator)

Groovy中引入了指数运算符**。如2 ** 3表示为2的三次方。

// base and exponent are ints and the result can be represented by an Integer
// 基数和指数都是int,所得结果可以用int表示,那么结果就是int类型
assert 2**3 instanceof Integer    //  8
assert 10**9 instanceof Integer   //  1_000_000_000

// the base is a long, so fit the result in a Long
// (although it could have fit in an Integer)
// 基数是long类型,所以结果也是long类型,尽管用int就足够表示
assert 5L**2 instanceof Long       //  25

// the result can't be represented as an Integer or Long, so return a BigInteger
// 当结果超过了int和long的表示范围,用BigInteger表示
assert 100**10 instanceof BigInteger   //  10e20
assert 1234**123 instanceof BigInteger //  170515806212727042875...

// the base is a BigDecimal and the exponent a negative int
// but the result can be represented as an Integer
assert 0.5**-2 instanceof Integer    //  4

// the base is an int, and the exponent a negative float
// but again, the result can be represented as an Integer
assert 1**-0.3f instanceof Integer    //  1

// the base is an int, and the exponent a negative int
// but the result will be calculated as a Double
// (both base and exponent are actually converted to doubles)
assert 10**-1 instanceof Double     //  0.1

// the base is a BigDecimal, and the exponent is an int, so return a BigDecimal
assert 1.2**10 instanceof BigDecimal //  6.1917364224

// the base is a float or double, and the exponent is an int
// but the result can only be represented as a Double value
assert 3.4f**5 instanceof Double     //  454.35430372146965
assert 5.6d**2 instanceof Double     //  31.359999999999996

// the exponent is a decimal value
// and the result can only be represented as a Double value
assert 7.8**1.9 instanceof Double     //  49.542708423868476
assert 2**0.1f instanceof Double     //  1.0717734636432956

Elvis Operator

在Java中,我们有时会用三元运算符来简化代码,比如下边的例子:

String name = getName(); // 假设这个方法可能返回空值,如果我们想在为空时赋上一个默认值

// 写法1,普通写法
if (name == null) {
    name = "unknow";
}

// 写法2,使用三元运算符
name = name != null ? name : "unknow";

在Groovy中,可以使用Elvis operator来进一步简化:

def name = getName()
name = name ?: 'unknown' // 在Groovy真值中,非空也为true
println name

安全访问运算符(Safe navigation operator)

我们可以通过一个点.来访问一个对象的属性或方法,但很多时候我们拿到的变量可能是null。这时如果我们直接使用.去访问,就有可能抛出空指针异常。而Groovy的安全访问运算符?.可以很好地解决这个问题:

def person = getPerson() // 假设该方法可能返回null
def name = person?.name // 如果person不为null,那返回具体的值;如果为null,也不会抛出异常,而是返回null

直接属性访问运算符(Direct field access operator)

先看一个例子:

class User {
    public final String name

    User(String name) { this.name = name }

    String getName() { "Name: ${name}" }
}

def user = new User('Bob')
assert user.name == 'Name: Bob' // 这里看似是访问属性name,但其实是调用getName方法

上面例子中,我们直接使用user.name其实相当于user.getName()。如果需要直接访问属性,需要使用.@这个运算符:

// 接上边的例子
assert user.@name == 'Bob'

方法指针运算符(Method pointer operator)

使用.&可以取一个方法的指针,而所谓的方法指针,其实是Groovy中的闭包

def str = 'example of method reference'
def fun = str.&toUpperCase // 取String的toUpperCase方法指针
println fun.class // class org.codehaus.groovy.runtime.MethodClosure
def upper = fun() // 这里相当于调用了方法
assert upper == str.toUpperCase()

展开运算符(Spread Operator)

Groovy中的展开运算符(*.)很有意思,它用于展开集合元素。

class Car {
    String make
    String model
}

def cars = [
        new Car(make: 'Peugeot', model: '508'),
        new Car(make: 'Renault', model: 'Clio')]
def makes = cars*.make // 相当于访问了每一个元素的make
assert makes == ['Peugeot', 'Renault'] // 结果还是一个列表

范围运算符(Range operator)

使用..可以定义一个范围:

def range = 0..5
println range.class // class groovy.lang.IntRange
assert (0..5).collect() == [0, 1, 2, 3, 4, 5]
assert (0..<5).collect() == [0, 1, 2, 3, 4] // 相当于左闭右开区间
assert (0..5) instanceof List // Range实现了List接口
assert (0..5).size() == 6

飞船运算符(Spaceship operator)

<==>像不像一个宇宙飞船?相当于调用compareTo方法:

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

成员运算符(Membership operator)

in相当于inCase方法,当用在列表上时,相当于调用列表的contains方法:

def list = ['Grace', 'Rob', 'Emmy']
assert ('Emmy' in list) // 相当于list.contains('Emmy')或list.isCase('Emmy')

身份运算符(Identity operator)

在Groovy中==相当于调用equals方法,如果要判断两个对象是否是同一个,需要使用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 // 相当于list.equals(list2)
assert !list1.is(list2)

运算符重载(Operator overloading)

Groovy中支持运算符重载,其实也就是实现约定好的方法:

class Bucket {
    int size

    Bucket(int size) { this.size = size }

    Bucket plus(Bucket other) { // 重载这个以实现+操作
        return new Bucket(this.size + other.size)
    }
}

def b1 = new Bucket(4)
def b2 = new Bucket(11)
assert (b1 + b2).size == 15 // 这里相当于(b1.plus(b2)).size

下面是支持重载的运算符与相应方法的对照表:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • C++运算符重载-下篇 本章内容:1. 运算符重载的概述2. 重载算术运算符3. 重载按位运算符和二元逻辑运算符4...
    Haley_2013阅读 1,434评论 0 49
  • C++运算符重载-上篇 本章内容:1. 运算符重载的概述2. 重载算术运算符3. 重载按位运算符和二元逻辑运算符4...
    Haley_2013阅读 2,282评论 0 51
  • 前言 人生苦多,快来 Kotlin ,快速学习Kotlin! 什么是Kotlin? Kotlin 是种静态类型编程...
    任半生嚣狂阅读 26,145评论 9 118
  • Groovy是一门基于JVM的动态语言,很多语法和Java类似。大部分Java代码也同时是合法的Groovy代码。...
    乐百川阅读 3,577评论 0 15
  • 去年年底开始,互联网蓬勃发展,“碎片化学习”成了热门话题。一下子让人觉得现在我们的时间因为互联网的发展,被碎片到了...
    流动盛宴爱码士阅读 6,123评论 1 2