Groovy运算符

作者: yjiyjige | 来源:发表于2016-06-13 01:54 被阅读3069次

官方文档

与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

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

相关文章

网友评论

    本文标题:Groovy运算符

    本文链接:https://www.haomeiwen.com/subject/tgcydttx.html