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方法后线程进入睡眠状态,直到以下事件发生:
- 其他线程调用了该对象的notify/notifyAll方法
- 其他线程调用interrupt中断了该线程
- 时间间隔到了
finalize()
该方法用于释放资源,当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法
当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法
判断两个对象是否相等(对象的内容和hashcode必须相等)
1.==和equals区别
- ==用于判断对象的地址是否相等
- equals方法也用作判断对象是否相等,有两种情况:
- 类没有覆盖equals方法,则当用equals比较该类的两个对象时,相当于调用父类的equals方法,等同于==。
- 类覆盖了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 +
'}';
}
}
虽然p1和p2的内容相等,但是我没有重写hashcode方法,所以p1、p2的hashcode不相等;我们知道hashset中不能有相同对象,但是测试用例中竟然有两个同样的Person对象,原因如下:
hashset在添加元素时会做以下判断
- 如果添加的元素的hashcode相等并且equals比较时也为true,就认为是同一个元素。
- 如果不符合上面的条件,就会认为添加的元素是一个新元素。
样例,简单重写了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 的两个对象无论如何都不会相等(即使这两个对象指向相同的数据)
参考
http://www.cnblogs.com/shenliang123/archive/2012/04/16/2452206.html
Object中的方法以及对象相等的判定的更多相关文章
- Python_day8_面向对象(多态、成员修饰符、类中特殊方法、对象边缘知识)、异常处理之篇
一.面向对象之多态 1.多态:简而言子就是多种形态或多种类型 python中不支持多态也用不到多态,多态的概念是应用与java/C#中指定传参的数据类型, java多态传参:必须是传参数的数据类型或传 ...
- hashCode -哈希值,Object中的方法,常根据实际情况重写
package cn.learn.collection; import cn.learn.basic.Phone; /* 哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值),是一个逻辑地址 ...
- Object中toString方法
在Java中,所有的对象都是继承自Object,自然继承了toString方法,在当使用System,out.println()里面为一个对象的引用时,自动调用toString方法将对象打印出来.如果 ...
- Java中的equals和==的区别以及几个常用的object中的方法简单的调试方法
一.equals 1.equals:是Object类中的方法,只能判断引用类型 2.默认判断的是地址是否相等(判断两个参数是否是同一个对象),子类中往往重写该方法,用于判断内容(值)是否相等 二.== ...
- tp5依赖注入(自动实例化):解决了像类中的方法传对象的问题
app\index\Demo1.php namespace app\index\controller; /* 容器与依赖注入的原理 ----------------------------- 1.任何 ...
- Object中的方法
1.equals() 2.toString() package com_package1; public class Person44 { private int age; public int ge ...
- 方法object面试题分析:7JAVA中Object的clone方法详解-克隆-深克隆
时间紧张,先记一笔,后续优化与完善. 每日一道理 翻开早已发黄的页张,试着寻找过去所留下的点点滴滴的足迹.多年前的好友似乎现在看来已变得陌生,匆忙之间,让这维持了多年的友谊变淡,找不出什么亲切 ...
- java中equal方法总结
场景:本周在完成一个公司业务功能时,在判断是否为代叫单时调用了equal方法: PublishOrderType.HELP_ORDER.equals(valetOrderExtraInfoDO.get ...
- Java中clone方法的使用
什么是clone 在实际编程过程中,我们常常要遇到这种情况:有一个对象object1,在某一时刻object1中已经包含了一些有效值,此时可能会需要一个和object1完全相同新对象object2,并 ...
随机推荐
- Java 设计模式系列(十七)中介者模式
Java 设计模式系列(十七)中介者模式 用一个中介对象来封装一系列的对象交互.中介者使得各对象不需要显式地相互引用,从而使其耦合松散,而且可以独立的改变它们之间的交互 一.中介者模式结构 Media ...
- 设置div中的div居中显示
设置div中的div居中显示 方法一. <div class='big'> <div class='small'>box1</div> </div> s ...
- centos环境下输入命令不能有中文那么我怎么插入中文数据到数据库
centos环境下输入命令不能有中文那么我怎么插入中文数据到数据库 如下图: 首先查看是否安装了中文语言支持组件 yum grouplist 没有的话安装 yum install Chinese Su ...
- 马婕 2014MBA专硕考试 词汇每日一练(转)
2013-6-8 1. To ensure its sustained progress in economy, the government has _______ a series of poli ...
- parseInt(string, radix)
参数 描述 string 必需.要被解析的字符串. radix 可选.表示要解析的数字的基数.该值介于 2 ~ 36 之间. 如果省略该参数或其值为 0,则数字将以 10 为基础来解析.如果它以 “0 ...
- ServiceStack.Text json中序列化日期格式问题的解决
标记: ServiceStack.Text,json,序列化,日期 在使用ServiceStack.Text的序列化为json格式的时候,当属性为datetime的时候,返回的是一个new date( ...
- Firefox mobile (android) and orientationchange
Firefox for Android does not support the orientationchange event but you can achieve the same result ...
- jenkins启动失败,提示Starting Jenkins Jenkins requires Java8 or later, but you are running 1.7.0
# 背景 centos安装jenkins后,先启动jenkins服务,结果报错如下: 但自己明明已经安装了java8的 # 解决方法 既然安装了java8的话,那么证明是jenkins启动的是还是用的 ...
- 基于Quartz.net的远程任务管理系统 二
紧接着上一篇.上一篇讲了表设计与ADO.Net基本操作.接下来,就来说说怎么动态来添加Job任务及清理过期任务吧. 首先,先理一下思路,做事情要先把思绪理清了,然后下手就快准狠了.下面是我的思路:做一 ...
- C#——Socket
最近公司让我搞个socket小程序(服务端). 主要的功能:客户端发字符串到服务端,服务端接收后在界面上显示. 参照了网上许多代码,自己从中修改整理代码. public Form4() { Initi ...