Object中的⽅法以及对象相等的判定
看图说话
Object有以下⼏个⽅法
getClass()
final类型,主要是⽤来获得运⾏时的类型
hashCode()
返回该对象的哈希码值,⽅法是为了提⾼哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。该⽅法常⽤于hash查,重写equals⽅法⼀般都要重写hashCode⽅法
equals()
equals⽅法⼀般和==是不⼀样的,但是在Object中,两者⼀样。⼦类⼀般都要重写这个⽅法
clone()
创建并返回对象的副本,它实现对象的浅复制
toString()
返回对象的字符串表⽰
notify()
唤醒在该对象上等待的某个线程
notifyAll()
唤醒在该对象上等待的所有线程
wait()
wait⽅法就是使当前线程等待该对象的锁,当前线程必须是该对象的拥有者,也就是具有该对象的锁。wait⽅法⼀直等待,直到获得锁或者被中断。wait(long timeout)设定了⼀个超时间隔,如果在规定时间没有获得锁就返回。
调⽤wait⽅法后线程进⼊睡眠状态,直到以下事件发⽣:
1. 其他线程调⽤了该对象的notify/notifyAll⽅法
2. 其他线程调⽤interrupt中断了该线程
3. 时间间隔到了
finalize()
该⽅法⽤于释放资源,当垃圾回收器确定不存在对该对象的更多引⽤时,由对象的垃圾回收器调⽤此⽅法
当垃圾回收器确定不存在对该对象的更多引⽤时,由对象的垃圾回收器调⽤此⽅法
判断两个对象是否相等(对象的内容和hashcode必须相等)
1.==和equals区别
==⽤于判断对象的地址是否相等
equals⽅法也⽤作判断对象是否相等,有两种情况:
1. 类没有覆盖equals⽅法,则当⽤equals⽐较该类的两个对象时,相当于调⽤⽗类的equals⽅法,等同于==。
2. 类覆盖了equals⽅法,⼀般会将equals重写成判断两个对象的内容是否相等,如果它们的内容相等,就返回true。
举个例⼦:
public class Person {
private int age;
public Person(int age) {
this.age = age;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public static void main(String[] args) {
Person p1 = new Person(10);
Person p2 = new Person(10);
String s1 = new String("123");
String s2 = new String("123");
System.out.println(p1 .equals(p2));#false
System.out.println(s1.equals(s2));#true
}
}
解析
虽然Person对象的内容相等,但是未复写equals⽅法,执⾏的还是Object中的equals⽅法,⽐较的还是地址
String中重写了equals⽅法,⽐较的是对象的内容
String中equals源码:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
//判断对象是否是String类型
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
2.hashcode与equals的关系
hashcode的作⽤是⽤来获取哈希码,也称作散列码。返回的类型是int,⽤于确定对象在hash表中的位置。Object中有hashcode⽅法,意味着所有的类都有hashcode⽅法。
为什么在重写equals⽅法时,需要重写hashcode⽅法?
为了提⾼程序的效率才实现hashCode⽅法,两个对象在进⾏⽐较的时候,如果它们的hashCode不相等,那么就没有必要进⾏equals⽅法⽐较了。
举个例⼦:在集合中,List集合中的元素是有序的,元素可以重复的;set集合是⽆序的,元素不能重复。那么如何保证集合⾥的元素是不能重复的,虽然可以使⽤equals⽅法,但是效率太低。假如集合⾥
的元素本来有10000个,那么再新增⼀个元素,如果⼀个⼀个⽐较,那么效率实在太低。这时候就体现hashcode的优势了,java采⽤hash表,利⽤哈希算法,就是将对象数据根据该对象的特征使⽤特定的算法将其定义到⼀个地址上,那么在后⾯定义进来的数据,只要看对应的hashcode地址上是否有值,那么就⽤equals⽐较,如果没有则直接插⼊,只要就⼤⼤减少了equals的使⽤次数,执⾏效率就⼤⼤提⾼了。
样例,重写了equals⽅法,没有重写hashcode⽅法:
public class Person {
private int age;
public Person(int age) {
this.age = age;
}
//getter、setter⽅法略
@Override
public boolean equals(Object obj) {
return true;
}
public static void main(String[] args) {
Person p1 = new Person(10);
Person p2 = new Person(10);
System.out.println("p1:"+p1.hashCode());#p1:1163157884
System.out.println("p2:"+p2.hashCode());#p2:1956725890
System.out.println(p1 .equals(p2));#true
HashSet<Object> hashSet = new HashSet<>();
hashSet.add(p1);
hashSet.add(p2);
System.out.println(hashSet);#[Person{age=10}, Person{age=10}]
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';equals()方法
}
}
虽然p1和p2的内容相等,但是我没有重写hashcode⽅法,所以p1、p2的hashcode不相等;我们知道hashset中不能有相同对象,但是测试⽤例中竟然有两个同样的Person对象,原因如下:
hashset在添加元素时会做以下判断
1. 如果添加的元素的hashcode相等并且equals⽐较时也为true,就认为是同⼀个元素。
2. 如果不符合上⾯的条件,就会认为添加的元素是⼀个新元素。
样例,简单重写了equals⽅法和hashcode⽅法:
public class Person {
private int age;
public Person(int age) {
this.age = age;
}
//getter、setter⽅法略
@Override
public boolean equals(Object obj) {
return true;
}
@Override
public int hashCode() {
return 0;
}
public static void main(String[] args) {
Person p1 = new Person(10);
Person p2 = new Person(10);
System.out.println(p1 .equals(p2));# true
System.out.println("p1:"+p1.hashCode());# 0
System.out.println("p2:"+p2.hashCode());# 0
HashSet<Object> hashSet = new HashSet<>();
hashSet.add(p1);
hashSet.add(p2);
System.out.println(hashSet);#[Person{age=10}]
[Person{age=10}]
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
'}';
}
}
从结果看出,p1、p2的内容相等并且hashcode也相等,hashset中只有⼀个元素。
⼩结
如果两个对象相等,则hashcode⼀定也是相同的
两个对象相等,对两个对象分别调⽤equals⽅法都返回true
两个对象有相同的hashcode值,它们也不⼀定是相等的
因此,equals ⽅法被覆盖过,则 hashCode ⽅法也必须被覆盖
hashCode() 的默认⾏为是对堆上的对象产⽣独特值。如果没有重写 hashCode(),则该 class 的两个对象⽆论如何都不会相等(即使这两个对象指向相同的数据)
参考
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论