我们平时在java开发过程中,经常可能会遇到要对字符参数做一些比较,其中比较常用的就不能不说equals方法了,那么你知道你经常用的String的equals是怎么实现的吗?怎么去重写equals方法呢?
我们先看一下Object类的equals方法的实现:
public static bool Equals(object objA, object objB) { if (objA == objB) //如果两个对象的引用相同,都指向同一个对象那么肯定是相等 { return true; } if ((objA != null) && (objB != null)) //如果两个对象之一为null 那么肯定不相当 { return objA.Equals(objB); } return false; } public virtual Boolean Equals(Object obj) { if (this == obj) return true; //如果两个对象的引用相同,都指向同一个对象那么肯定是相等 return false; }
其实在设计类型的时候我们可以分3种情况:
我们当前所设计的引用类的基类型如果说没有重写Object的Equals方法而是直接继承得来,那么实现Equals方法可以这样:
lass MyRefType: BaseType { RefType refobj; ValType valobj; public override Boolean Equals(Object obj) { if (obj == null) return false; //当前对象this不可能为null,所以如果obj为null,那么肯定不相等 if (this.GetType() != obj.GetType()) return false; //如果连类型都不同,那么肯定不相同啦 MyRefType other = (MyRefType) obj; //因为类型已经可以肯定相同,转换安全 if (!Object.Equals(refobj, other.refobj)) return false; //比较引用类型字段,这里只有用Object的静态方法Equals来比较,为什么?刚才看了Object的静态方法实现,其中是使用比较对象之一的实例方法Equals来比较的,而我们现在正在这个类型的实例方法Equals中,这样会不会引起循环引用? if (!valobj.Equals(other.valobj)) return false; //比较值类型字段 return true; //到这里两个对象才相同 } public static Boolean operator == (MyRefType o1, MyRefType o2) { return Object.Equals(o1, o2); } public static Boolean operator != (MyRefType o1, MyRefType o2) { return !(o1 == o2); } }
当我们从Object类的静态Equals方法的实现可以看出实现Equals方法时,只要实现当前类型的实例方法Equals就行了,静态方法也就可以免了,直接调用Object类的静态Equals方法即可,因为最终比较还是要使用这个子类的实例方法。
如果说我们当前所设计的引用类的基类型重写了Object的Equals方法,那么实现Equals方法可以这样:
class MyRefType: BaseType { RefType refobj; ValType valobj; public override Boolean Equals(Object obj) { if (!base.Equals(obj)) return false; //如果连基类型都认为对象不相等,那么就不可能相等 if (obj == null) return false; //当前对象this不可能为null,所以如果obj为null,那么肯定不相等 if (this.GetType() != obj.GetType()) return false; //如果连类型都不同,那么肯定不相同啦 MyRefType other = (MyRefType) obj; //因为类型已经可以肯定相同,转换安全 if (!Object.Equals(refobj, other.refobj)) return false; //比较引用类型字段,这里只有用Object的静态方法Equals来比较,为什么?刚才看了Object的静态方法实现,其中是使用比较对象之一的实例方法Equals来比较的,而我们现在正在这个类型的实例方法Equals中,这样会不会引起循环引用? if (!valobj.Equals(other.valobj)) return false; //比较值类型字段 return true; //到这里两个对象才相同 } public static Boolean operator == (MyRefType o1, MyRefType o2) { return Object.Equals(o1, o2); } public static Boolean operator != (MyRefType o1, MyRefType o2) { return !(o1 == o2); } }
注意:当基类按照自己的逻辑重写Object的Equals方法时,那么必须先调用基类的Equals方法来判断,否则我们的Equals实现可能总是先判断两个对象的引用是否相同,这样可能大部分情况下都是永远返回false。
为值类型实现Equals方法:
先来看看System.ValueType的Equals方法的实现:
public override bool Equals(object obj) { if (obj == null) { return false; } RuntimeType type1 = (RuntimeType) base.GetType(); //获取运行时类型 RuntimeType type2 = (RuntimeType) obj.GetType(); if (type2 != type1) //类型都不同,就没有机会相等 { return false; } object obj1 = this; if (ValueType.CanCompareBits(this)) { return ValueType.FastEqualsCheck(obj1, obj); } FieldInfo[] infoArray1 = type1.InternalGetFields(BindingFlags.NonPublic | (BindingFlags.Public | BindingFlags.Instance), false); for (int num1 = 0; num1 < infoArray1.Length; num1++) //比较每个字段的值 { object obj2 = ((RuntimeFieldInfo) infoArray1[num1]) .InternalGetValue(obj1, false); object obj3 = ((RuntimeFieldInfo) infoArray1[num1]) .InternalGetValue(obj, false); if (obj2 == null) { if (obj3 != null) { return false; } } else if (!obj2.Equals(obj3)) { return false; } } return true; } 可以这样实现: struct MyValType { RefType refobj; ValType valobj; publci override Boolean Equals(Object obj) { if (!(obj is MyValType)) return false; return this.Equals((MyValType) obj); } public Boolean Equals(MyValType obj) { if (!Object.Equals(this.refobj, obj.refobj)) return false; if (!this.valobj.Equals(obj.valobj)) return false; return true; } public static Boolean operator == (MyValType v1, MyValType v2) { return v1.Equals(v2); } public static Boolean operator != (MyValType v1, MyValType v2) { return !(v1 == v2); } }
好了,以上就是有关String中的equals实现的所有内容了,还想了解更多java常见问答记得来关注本站消息哦。