今天看java.util.Comparator 这个接口,看到里面除了有个 int compare(T o1,T o2); 这个抽象方法外,还有 boolean equals(Object obj);这个抽象方法。
我看到的代码,都没有实现这个抽象方法,(包括自己写代码,也没有实现),程序也不报错,是否说明这个方法在实现这个接口的类的父类(Object)已经实现了?
假设是这样的话,那这个方法就不需要定义了,(因为接口都要由类实现,而所有的类都是Object的子类,那自然都继承了这个方法,当然可以重写。
如果不是这样的话,那它的意义究竟是什么呢?
可能说的不清楚,简单的说,既然Object类里有了的方法,为什么在接口里还要定义抽象方法?
我看到的代码,都没有实现这个抽象方法,(包括自己写代码,也没有实现),程序也不报错,是否说明这个方法在实现这个接口的类的父类(Object)已经实现了?
假设是这样的话,那这个方法就不需要定义了,(因为接口都要由类实现,而所有的类都是Object的子类,那自然都继承了这个方法,当然可以重写。
如果不是这样的话,那它的意义究竟是什么呢?
可能说的不清楚,简单的说,既然Object类里有了的方法,为什么在接口里还要定义抽象方法?
* <tt>Object.equals(Object)</tt>. However, overriding this method may,
* in some cases, improve performance by allowing programs to determine
* that two distinct comparators impose the same order.
比如我们在Hibernate中采用复合主键类时:
我们的Person类:Person.java
@Entity
@Table(name="peroson_table")
public class Person
{
/*指定使用复合主键类是Name*/
@EmbeddedId
@AttributeOverrides({
@AttributeOverride(name="first",column=@Column(name="person_first")),
@AttributeOverride(name="last",columen=@Column(name="person_last",length=20))
})
private Name name;
//普通属性
@Column(name="person_email")
private String email;
...Name属性的set和get方法
...Email属性的set和get方法
})
//Person的Name属性就是一个复合类型的标识属性}那么在Name类中我们要实现java.io.Serializable接口并重写hashCod()和equals()方法:
Name.java//修饰组件属性类
@Embeddable
Piblic class Name implements java.io.Serializable
{
Private String first;
Private String last;
//无参数的构造器
Public name()
{
}
//初始化全局属性的构造器
Public Name(String first,String laset)
{
This.first=first;
This.last=last;
}
...first属性的set、get方法
...last属性的set、get方法
//提供重写的equals方法
Public boolean equals(Object obj)
{
If(this==obj)
{
Return true;
}
If(obj.getClass()==Name.class)
{
Name target = (Name)obj;
If(target.getFirst().equals(first) && target.getLast().equals(last))
{
Return true;
}
}
Return false;
}
//提供重写的hashCode方法
Public int hashCode()
{
Return fist.hashCode()+last.hashCod()*17;
}
}
api5。0翻译的是这样的:注意,不 重写 Object.equals(Object) 方法总是 安全的。然而,在某些情况下,重写此方法可以允许程序确定两个不同的 Comparator 是否强行实现了相同的排序,从而提高性能。 为什么说不重写是安全的? 这是针对什么说的?
重写怎么能提高性能?
1.Object类并没有实现Comparator接口。
2.如果你在你的代码中使用compare方法,还是需要自己写的。
3.能否把代码贴上来,以供仔细查看。
首先,为什么说不重写equals总是安全的。因为java中很多Collection你在取值时,实际是通过hashCode()来实现的。如果你重写了object的equals方法,可能意味着原来不相等的两个值现在奇怪的相等了,或是两个原来相等的值现在相等了。由此可能造成你原来存进去的值现在没法取出来。
再者,为什么Comparator也有一个equals方法。接口是并不继承Object类的。这个方法用来比较其他对象是否等于这个比较器。当指定的对象也是一个比较器,并且和这个Comparator执行相同的顺序时,该方法返回true.
参考资料:http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html
“再者,为什么Comparator也有一个equals方法。接口是并不继承Object类的。这个方法用来比较其他对象是否等于这个比较器。当指定的对象也是一个比较器,并且和这个Comparator执行相同的顺序时,该方法返回true.”
实际上我的问题就在这,接口虽然不是继承Object类,但实现接口的类肯定是继承Object的,那么这个类就会有equals()方法了。如果需要重写,就重写;不需要,可以不用管。 所以我不知道到底这个接口里定义的这个equals()有什么用?或者说,明明是已经有了的方法,为什么还要重复定义?
注意,不去重写Object的equals方法总是安全的。但是,重写这个方法也许,在某些情况下,(有助于)提高效率,——因为这就允许程序作出这样的判断:两个不同的Comparator实现导致的排序结果其实是相同的。(比如两个Comparator分别对同一个巨大的集合排序,你要想知道结果是不是相同,就可以通过两个 Comparator 的 equals 结果知道,而不用去比较两个巨大的结果集合了)接口里面写上这个方法,我猜就是为了能有一个合适的地方写下这段注释,提醒程序员注意到这种对Comparator实现重写equals的可能性。当然,根据Object类里的equals协议,如果重写equals那就是说hashCode也要同时重写,这个还是要遵守的。