According to the Groovy docs, the ==
is just a "clever" equals()
as it also takes care of avoiding NullPointerException
:
Java’s
==
is actually Groovy’sis()
method, and Groovy’s==
is a cleverequals()
![...]
But to do the usual
equals()
comparison, you should prefer Groovy’s==
, as it also takes care of avoidingNullPointerException
, independently of whether the left or right isnull
or not.
So, the ==
and equals()
should return the same value if the objects are not null. However, I'm getting unexpected results on executing the following script:
println "${'test'}" == 'test' println "${'test'}".equals('test')
The output that I'm getting is:
true false
Is this a known bug related to GStringImpl
or something that I'm missing?
== is symmetric in groovy. While that table is super handy, it's a bit misleading as == isn't actually on it.
Thankfully, a different portion of the Groovy Language Documentation saves the day: Behaviour of == In Java == means equality of primitive types or identity for objects. In Groovy == translates to a. compareTo(b)==0, if they are Comparable, and a. equals(b) otherwise.
== is a relational operator which checks if the values of two operands are equal or not, if yes then condition becomes true. equals() is a method available in Object class and is used to compare objects for equality.
Nice question, the surprising thing about the code above is that
println "${'test'}".equals('test')
returns false
. The other line of code returns the expected result, so let's forget about that.
"${'test'}".equals('test')
The object that equals
is called on is of type GStringImpl
whereas 'test'
is of type String
, so they are not considered equal.
Obviously the GStringImpl
implementation of equals
could have been written such that when it is passed a String
that contain the same characters as this
, it returns true. Prima facie, this seems like a reasonable thing to do.
I'm guessing that the reason it wasn't written this way is because it would violate the equals
contract, which states that:
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
The implementation of String.equals(Object other)
will always return false when passed a GSStringImpl
, so if GStringImpl.equals(Object other)
returns true when passed any String
, it would be in violation of the symmetric requirement.
In groovy a == b
checks first for a compareTo
method and uses a.compareTo(b) == 0
if a compareTo
method exists. Otherwise it will use equals
.
Since Strings and GStrings implement Comparable
there is a compareTo
method available.
The following prints true, as expected:
println "${'test'}".compareTo('test') == 0
The behaviour of ==
is documented in the Groovy Language Documentation:
In Java
==
means equality of primitive types or identity for objects. In Groovy==
means equality in all cases. It translates toa.compareTo(b) == 0
, when evaluating equality forComparable
objects, anda.equals(b)
otherwise. To check for identity (reference equality), use theis
method:a.is(b)
. From Groovy 3, you can also use the===
operator (or negated version):a === b
(orc !== d
).
The full list of operators are provided in the Groovy Language Documentation for operator overloading:
Operator | Method |
---|---|
+ | a.plus(b) |
- | a.minus(b) |
* | a.multiply(b) |
/ | a.div(b) |
% | a.mod(b) |
** | a.power(b) |
| | a.or(b) |
& | a.and(b) |
^ | a.xor(b) |
as | a.asType(b) |
a() | a.call() |
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() |
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With