59

根据Groovy 文档,这==只是一个“聪明的” equals(),因为它还负责避免NullPointerException

Java 的==实际上是 Groovy 的is()方法,而 Groovy 的方法==很聪明equals()

[...]

但是要进行通常的equals()比较,您应该更喜欢 Groovy 的==,因为它还负责避免NullPointerException,无论左右是否null存在。

因此,如果对象不为空, ==and应该返回相同的值。equals()但是,我在执行以下脚本时得到了意想不到的结果:

println "${'test'}" == 'test'
println "${'test'}".equals('test')

我得到的输出是:

true
false

这是一个已知的错误,GStringImpl还是我遗漏的东西?

4

2 回答 2

74

好问题,关于上面的代码令人惊讶的是

println "${'test'}".equals('test')

返回false。另一行代码返回预期的结果,所以让我们忘记这一点。

概括

"${'test'}".equals('test')

被调用的对象equals是 typeGStringImpl而是'test'type String,所以它们不被认为是相等的。

但为什么?

显然, 的GStringImpl实现equals可以这样写,当它传递一个String包含与 相同的字符时this,它返回true。从表面上看,这似乎是一件合理的事情。

我猜它不是这样写的原因是因为它会违反equals合同,合同规定:

它是对称的:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应该返回 true。

的实现String.equals(Object other)在传递 a 时将始终返回 false GSStringImpl,因此如果GStringImpl.equals(Object other)在传递 any 时返回 true String,则违反对称要求。

于 2012-03-13T10:52:22.247 回答
55

在 groovya == b中,首先检查compareTo方法并a.compareTo(b) == 0compareTo方法存在时使用。否则它将使用equals.

由于 Strings 和 GStrings 实现Comparable了一个compareTo可用的方法。

正如预期的那样,以下打印结果为真:

println "${'test'}".compareTo('test') == 0

的行为==记录在Groovy 语言文档中:

在 Java==中意味着原始类型的相等性或对象的身份。在 Groovy==中意味着在所有情况下都是平等的。a.compareTo(b) == 0在评估Comparable对象的相等性时,它转换为,a.equals(b)否则转换为 。要检查身份(引用相等),请使用is方法:a.is(b). 从 Groovy 3 开始,您还可以使用===运算符(或否定版本):(a === bc !== d)。

运算符重载的 Groovy 语言文档中提供了运算符的完整列表:

操作员 方法
+ a.加(b)
- a.减号(b)
* a.乘法(b)
/ a.div(b)
% a.mod(b)
** a.power(b)
| a.或(b)
& a.和(b)
^ a.xor(b)
as a.asType(b)
a() 一个电话()
a[b] a.getAt(b)
a[b] = c a.putAt(b, c)
a in b b.isCase(a)
<< a.leftShift(b)
>> a.rightShift(b)
>>> a.rightShiftUnsigned(b)
++ a.next()
-- a.previous()
+a a.positive()
-a a.negative()
~a a.bitwiseNegate()
于 2012-03-13T10:44:21.973 回答