This is described here.
Basically in Java == with primitive types means use equality. For object types == means test identity.
We found when working with Groovy that if we kept those semantics and folks used dynamic typing as follows
They would get surprising results, as they often mean equality based on value, such as in the above, rather than identity. Indeed folks rarely ever use identity comparisions.
So to avoid many common gotchas and confusions, we've made == mean equals, the meaning most developers use, and we use this for both primitive types and for object types and across both static and dynamic typing to simplify things.
Currently if you really want to compare identities of the objects, use the method is(), which is provided by every object.
The above condition is never true, since the Integer object in x (which is the result of the computation above) is not identical to the Integer object with value 4 that has been created for the comparison.