ZetCode

Groovy 运算符

最后修改日期:2025 年 3 月 22 日

在本文中,我们将探讨 Groovy 中的运算符,这些特殊符号对操作数(如数字、字符串或布尔值)执行操作。 Groovy 提供了一组丰富的运算符——算术、关系、逻辑以及独特的运算符(如 Elvis 和安全导航)——在 Java 的基础上增加了灵活性。 理解这些可以提高代码效率和可读性。

Groovy 符号运算符

符号运算符 +- 设置或反转值的符号,从而影响数字在表达式中的解释方式。 它们是一元的,作用于单个操作数,是数字操作的基础。

SignOperators.groovy
println(2)    // Positive by default
println(+2)   // Explicitly positive
println(-2)   // Negative

这里,2 隐式为正,+2 显式标记为正,-2 将其反转为负。 这些运算符在计算或动态取反值时,可以明确意图。

SignOperatorsAdvanced.groovy
def x = 5
def y = -x
println(y)
println(-y)

此示例将 5 分配给 x,然后使用 - 创建 y 为 -5。 -y 将其翻转回 5,展示了符号运算符如何在表达式中转换变量。

Groovy 赋值运算符

赋值运算符 = 将值绑定到变量,形成 Groovy 中数据存储的基础。 它是右结合的,这意味着多个赋值从右到左链接。

AssignmentOperator.groovy
def x = 10
println(x)

def x = 10 将 10 分配给 xdef 关键字动态声明 x,而 = 设置其值,然后将其打印出来。 简单但对所有程序都至关重要。

AssignmentChain.groovy
def a = b = 7
println(a)
println(b)

这里,a = b = 7 链式赋值。 从右到左评估,b 首先获得 7,然后 a 接收 b 的值 (7)。 这展示了赋值的结合性。

Groovy 连接字符串

+ 运算符在 Groovy 中兼作字符串连接符,将文本操作数组合成一个字符串。 它用途广泛,还可以通过隐式将数字转换为字符串来与数字一起使用。

ConcatenateStrings.groovy
def str = "Hello, " + "Groovy!"
println(str)

"Hello, " + "Groovy!" 将两个字符串合并为 "Hello, Groovy!"。 + 运算符无缝连接文字,创建一个新字符串存储在 str 中,展示了 Groovy 字符串处理的简易性。

ConcatenateMixed.groovy
def num = 42
def msg = "Answer: " + num
println(msg)

"Answer: " + num 混合了字符串和整数。 Groovy 将 num (42) 转换为字符串,结果为 "Answer: 42"。 这种隐式强制转换简化了不同类型的组合,无需额外的强制转换。

Groovy 递增和递减运算符

++-- 运算符将变量的值调整 1,向上或向下。 它们可以是前缀 (++x) 或后缀 (x++),影响更改在表达式中可见的时间。

IncDec.groovy
def x = 5
x++           // Postfix increment
println(x)
x--           // Postfix decrement
println(x)

x++ 在使用其原始值后将 x 从 5 增加到 6,而 x-- 将其降回 5。 后缀意味着该操作在当前表达式之后应用,从而改变 x 以供下次使用。

PrefixIncDec.groovy
def y = 10
println(++y)
println(--y)

++y 在打印之前将 y 递增至 11,而 --y 在下次打印之前将其递减至 10。 前缀运算符首先修改值,使更新后的结果立即在表达式中生效。

Groovy 算术运算符

算术运算符—+-*/%—对数字执行基本数学运算。 Groovy 处理带小数的除法和取余,与标准数学约定一致。

ArithmeticOperators.groovy
def a = 10
def b = 3

println(a + b)
println(a - b)
println(a * b)
println(a / b)
println(a % b)

a + b 加起来是 13,a - b 减去是 7,a * b 乘以是 30,a / b 除以大约是 3.33(双精度),而 a % b 给出余数 1。 这些运算符适用于整数或浮点数,除法产生精确的小数。

ArithmeticMixed.groovy
def x = 15.5
def y = 4
println(x - y)
println(x % y)

x - y 从 15.5 中减去 4,产生 11.5,一个浮点数。 x % y 计算余数 (15.5 = 3 * 4 + 3.5),显示 3.5。 此示例突出显示了混合数字类型的算术,保持精度。

Groovy 布尔运算符

布尔运算符—&&(AND)、||(OR)和 !(NOT)—操作 truefalse 值以进行逻辑条件判断。 它们是短路的,这意味着一旦确定结果,评估就会停止。

BooleanOperators.groovy
def x = true
def y = false

println(x && y)
println(x || y)
println(!x)

x && y 需要两者都为真(此处为假),x || y 需要一个为真(真),而 !x 将真反转为假。 这些构成了条件逻辑的核心,由于短路,可以有效地评估表达式。

BooleanShortCircuit.groovy
def a = false
def b = { println("Skipped"); true }()
println(a && b)

a && bfalse (a) 处停止,跳过 b 的闭包执行(不打印“Skipped”)。 这展示了短路:如果左操作数决定了结果,则不会评估右操作数,从而节省了计算。

Groovy 关系运算符

关系运算符—==!=<><=>=—比较值,返回布尔值。 它们适用于数字、字符串等,Groovy 具有宽松的类型比较。

RelationalOperators.groovy
def a = 10
def b = 20

println(a == b)
println(a != b)
println(a < b)
println(a > b)
println(a <= b)
println(a >= b)

a == b 检查相等(假),a != b 不相等(真),a < b 小于(真),依此类推。 这些运算符比较 a (10) 和 b (20),产生用于控制流或决策的逻辑结果。

RelationalStrings.groovy
def s1 = "apple"
def s2 = "banana"
println(s1 < s2)
println(s1 == "apple")

s1 < s2 按字典顺序比较(“apple”在“banana”之前),返回 true。 s1 == "apple" 确认相等。 Groovy 的关系运算符通过字母顺序处理字符串,使其用途超越了数字。

Groovy Elvis 运算符

Elvis 运算符 ?: 简化了空值检查,如果左侧操作数非空,则返回左侧操作数,否则返回右侧操作数。 它是用于默认值的 if-else 的简洁替代方案。

ElvisOperator.groovy
def name = null
def displayName = name ?: "Guest"
println(displayName)

name ?: "Guest" 评估 name(空值),因此它返回“Guest”。 Elvis 运算符缩短了空值处理,避免了冗长的检查,同时确保了回退,从而提高了代码的简洁性和安全性。

ElvisNonNull.groovy
def user = "Alice"
def result = user ?: "Unknown"
println(result)

user 为 "Alice"(非空)时,user ?: "Unknown" 返回 "Alice",跳过默认值。 这显示了运算符对有效值的行为,仅在必要时使用右侧操作数。

Groovy 安全导航运算符

安全导航运算符 ?. 通过在访问属性或方法之前返回 null(如果左侧操作数为 null),来防止 NullPointerException。 它是 Groovy 特有的安全网。

SafeNavigationOperator.groovy
def person = null
def name = person?.name
println(name)

person?.name 检查 person(空值),因此它返回 null 而不是崩溃。 如果没有 ?.,这将引发异常。 它非常适合安全地导航可能不完整的对象层次结构。

SafeNavigationValid.groovy
class User { String username = "Bob" }
def u = new User()
println(u?.username)

u 是有效的 User 对象时,u?.username 正常访问 "Bob"。 该运算符仅在为空时进行干预,使其在对象存在时是透明的,将安全性与简单性融为一体。

Groovy Spread 运算符

spread 运算符 *. 将方法或操作应用于集合的每个元素,返回新的结果列表。 它是用于批量处理的强大 Groovy 功能。

SpreadOperator.groovy
def numbers = [1, 2, 3, 4]
def squares = numbers*.multiply(2)
println(squares)

numbers*.multiply(2)numbers 中的每个元素加倍,产生 [2, 4, 6, 8]。 Spread 运算符在每个项目上调用 multiply,收集结果,简化了集合的迭代。

SpreadString.groovy
def words = ["cat", "dog"]
def lengths = words*.length()
println(lengths)

words*.length() 在每个字符串上调用 length(),为 "cat" 和 "dog" 返回 [3, 3]。 这显示了运算符在任何方法上的灵活性,而不仅仅是数字方法,从而增强了集合操作。

Groovy 运算符优先级

运算符优先级决定了表达式中的求值顺序,优先级较高的运算符(例如,*)在优先级较低的运算符(例如,+)之前执行。 Groovy 镜像了 Java 的规则,确保了可预测的数学运算。

Precedence.groovy
def result = 3 + 5 * 2
println(result)

3 + 5 * 2 中,由于优先级较高,乘法 (5 * 2 = 10) 优先于加法 (3 + 10 = 13),产生 13。 如果没有此顺序,则为 16,突出显示了优先级在复杂表达式中的重要性。

PrecedenceParens.groovy
def alt = (3 + 5) * 2
println(alt)

(3 + 5) * 2 使用括号(最高优先级)来强制首先进行加法 (8),然后进行乘法 (16)。 这会覆盖自然优先级,显示了如何显式控制求值顺序以获得所需的结果。

Groovy 结合性

结合性控制着相同优先级的运算符的顺序。 大多数 Groovy 运算符都是左结合的(从左到右),但赋值运算符和三元运算符是右结合的(从右到左),从而影响了链式操作。

Associativity.groovy
def a = 10
def b = 20
def c = 30

def result = a = b = c
println(result)

a = b = c 从右到左赋值:c (30) 到 b,然后 b (30) 到 a,以及 aresult。 右结合性确保链从最右边的值流动,将所有变量统一为 30。

LeftAssociativity.groovy
def val = 20 - 5 - 3
println(val)

由于左结合性,20 - 5 - 3 从左到右减:20 - 5 = 15,然后 15 - 3 = 12。 如果是右结合的,则为 20 - (5 - 3) = 18,说明了结合性如何使用等优先级的运算符来塑造结果。

Groovy 三元运算符

三元运算符 ?: 将 if-else 逻辑浓缩为一行,评估条件以在两个值之间进行选择。 它是右结合的,通常用于简洁的赋值或返回。

TernaryOperator.groovy
def age = 20
def status = age >= 18 ? "Adult" : "Minor"
println(status)

age >= 18 ? "Adult" : "Minor" 检查 age (20) 是否至少为 18(真),返回“Adult”。 如果为假,则返回“Minor”。 此运算符简化了简单的条件,减少了代码冗长。

TernaryNested.groovy
def score = 85
def grade = score > 90 ? "A" : score > 80 ? "B" : "C"
println(grade)

score > 90 ? "A" : score > 80 ? "B" : "C" 嵌套三元运算符。 由于 85 不 > 90(假),它检查 > 80(真),产生“B”。 右结合性将其解析为 score > 90 ? "A" : (score > 80 ? "B" : "C"),显示了多级决策。

Groovy 位运算符

位运算符—&(AND)、|(OR)、^(XOR)、~(NOT)—作用于整数位,对于低级操作(如标志或掩码)很有用。 结果取决于二进制表示形式。

BitwiseOperators.groovy
def a = 0b1010  // 10
def b = 0b1100  // 12

println(a & b)
println(a | b)
println(a ^ b)
println(~a)

a & b (1010 & 1100 = 1000) 产生 8,a | b (1010 | 1100 = 1110) 14,a ^ b (1010 ^ 1100 = 0110) 6,~a 将 1010 反转为 -11(补码)。 这些直接操作位,提供对二进制数据的精确控制。

BitwiseShift.groovy
def x = 8       // 0b1000
println(x << 1)
println(x >> 1)

x << 1 将 8 (1000) 左移,添加 0 (10000 = 16)。 x >> 1 右移,删除最后一位 (0100 = 4)。 移位运算符也是按位的,乘以或除以 2 的幂,从而扩展了按位实用程序。

Groovy 运算符优先级表

下表列出了 Groovy 运算符优先级,从最高到最低,指导如何在没有括号的情况下解析表达式。 它镜像了 Java 的约定以保持一致性。

运算符 描述
() 括号
++, -- 递增、递减
!, ~ 逻辑非、按位非
*, /, % 乘法、除法、取模
+, - 加法、减法
<<, >>, >>> 按位移位
<, <=, >, >= 关系运算符
==, != 相等运算符
& 按位与
^ 按位异或
| 按位或
&& 逻辑与
|| 逻辑或
?: 三元运算符
=+=-= 赋值运算符

来源

Groovy 运算符文档

在本教程中,我们探讨了如何在 Groovy 中使用运算符,包括算术、关系、逻辑和 Groovy 特定的运算符,如 Elvis 和安全导航运算符。 理解运算符对于编写高效且简洁的 Groovy 代码至关重要。

作者

我的名字是 Jan Bodnar,我是一位充满热情的程序员,拥有多年的编程经验。 我从 2007 年开始撰写编程文章。到目前为止,我已经撰写了 1400 多篇文章和 8 本电子书。 我有超过八年的编程教学经验。

列出 所有 Groovy 教程