Groovy与Java同是运行在JVM之上,大多数时候可以把Groovy当做Java来用,但是也存在着陷阱。
例如,想重写对象的equals方法,需如下步骤:
1. 使用==判断参数和自身对象引用是否相等,如果相等直接返回true(此判断可以提高性能);
2. 使用instanceof判断参数类型是否正确,如果不正确直接返回false
3. 将参数转换为正确的类型,步骤2已确保了类型
4. 检查参数与自身对象关键字段是否相等
1)基本类型(除float和double)运用==比较
2)对象引用,递归调用equals方法
3)浮点型float,调用Float.floatToIntBits转化为int,用==比较
4)浮点型double,调用Double.doubleToLongBits转化为long,用==比较
遵循以上步骤,重写简单Money类的equals方法:
1 public boolean equals(Object another) {
2 if (another == this) return true
3 if (another instanceof Money) {
4 Money anotherMoney = (Money) another
5 return amount == anotherMoney.amount
6 }
7 return false
8 }
调用
1 new Money(10).equals(new Money(10))
得到异常
java.lang.StackOverflowError
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:86)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:234)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1049)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:880)
at org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:746)
at org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:729)
at org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation.compareEqual(DefaultTypeTransformation.java:620)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.compareEqual(ScriptBytecodeAdapter.java:680)
at Money.equals(Money.groovy:10)
最终发现罪魁祸首是“==”,Groovy中对于所有类型(基本类型和引用)调用“==”和“equals()”方法相同,当执行“
another == this”时,解释器会调用“
another.equals(this)”造成死循环。
如果想比较引用相等,Groovy提供了is方法,即
1 public boolean equals(Object another) {
2 if (another.is(this)) return true
3 if (another instanceof Money) {
4 Money anotherMoney = (Money) another
5 return amount == anotherMoney.amount
6 }
7 return false
8 }