Groovy在GStringImpl上使用equals()和==会产生不同的结果



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

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

[…]

但是,要进行通常的equals()比较,您应该更喜欢Groovy的==,因为它还注意避免使用NullPointerException,而与左侧或右侧是否为null无关。

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

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

我得到的输出是:

true
false

这是一个已知的与GStringImpl有关的错误还是我缺少的东西?

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

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

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

摘要

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

调用equals的对象是GStringImpl类型,而'test'String类型,因此它们不被认为是相等的。

但是为什么

显然,equalsGStringImpl实现可以这样编写,即当它被传递一个包含与this相同字符的String时,它返回true。初步看来,这似乎是一件合理的事情

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

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

String.equals(Object other)的实现在传递GSStringImpl时总是返回false,因此如果GStringImpl.equals(Object other)在传递任何String时返回true,则违反对称要求。

在groovy中,a == b首先检查compareTo方法,如果存在compareTo方法,则使用a.compareTo(b) == 0。否则将使用equals

由于Strings和GStrings实现了Comparable,因此有一个compareTo方法可用。

如预期,以下打印结果为真:

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

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

在Java中,==表示对象的基元类型或标识相等。在Groovy中,==意味着在所有情况下都是相等的。当为Comparable对象计算相等性时,它转换为a.compareTo(b) == 0,否则,它转换成a.equals(b)。要检查身份(引用相等),请使用is方法:a.is(b)。从Groovy3中,您还可以使用===运算符(或否定版本):a === b(或c !== d)。

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

操作员方法
+a.plus(b)
-a.减去(b)
*a.乘(b)
/a.div(b)
%a.mod(b)
**a.功率(b)
|a.或(b)
&a.和(b)
^a.xor(b)
asa.as类型(b)
a()a.调用()
a[b]a.getAt(b)
a[b] = ca.putAt(b,c)
a in bb.is案例(a)
<<a.leftShift(b)
>>a.右移(b)
>>>a.rightShiftUnsigned(b)
++a.next()
--a.以前()
+aa.正()
-aa.否定()
~aa.bitwiseNegate()

将此作为附加答案留在这里,这样Groovy初学者就可以很容易地找到它。在比较之前,我将GString显式地转换为普通String

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

中的结果

false
true

相关内容

  • 没有找到相关文章