3、Object对象的两大方法(hashCode-equals)总结
Object类是所有java类的父类。
用户定义了如下一个Person类
public class Person{}
在类定义中并没有明确继承Object类,但是编译器会自动的完成这个过程。
既然所有类都继承自Object,那么它所具有的方法一定很重要。接下来就看看Object所具有的一些方法。
public class Object {
public final native Class<?> getClass();
public native int hashCode();
public boolean equals(Object obj) {
return (this == obj);
}
protected native Object clone() throws CloneNotSupportedException;
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
public final native void notify();
public final native void notifyAll();
public final native void wait(long timeout) throws InterruptedException;
public final void wait(long timeout, int nanos) throws InterruptedException {
if (timeout < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
timeout++;
}
wait(timeout);
}
public final void wait() throws InterruptedException {
wait(0);
}
}
Object类定义
当前主要关注hashCode、equals这两个方法。其它的后面涉及到相关内容的时候再做总结。
1、hashCode()方法总结
默认行为:
从定义我们看出,它是一个native方法,也就是它的具体实现不在java中,而是在操作系统的c/c++中。默认的hashCode方法会利用对象的地址来计算hashcode值,也就是说,不同对象的hashcode值是不一样的(即便是对象类型相同、属性值完全相同)。
hashCode方法应该满足的基本原则:
①、java应用的同一次执行过程中,在对象上 equals 比较中所用的信息没有被修改的前提下,多次调用相同对象的hashCode()必须得到相同的hashCode。上一次应用执行与下一次应用执行中的产生的hashCode值不要求保持一致。
②、如果obj1.equals(obj2)判定两个对象相等,那么obj1.hashCode()必须等于obj2.hashCode()。
③、如果obj1.equals(obj2)判定两个对象不相等,那么obj1.hashCode()与obj2.hashCode()的值可以相等,也可以不相等。当然,程序员应该注意到不相等的对象产生不相等的hashCode会提升hash表的性能(比如HashMap中使用到的)。
2、equals()方法
默认行为:
public boolean equals(Object obj) {
return (this == obj);
}
可以看出Object类中的equals方法与“==”是等价的,也就是说判断对象的地址是否相等。也就是说,Object类中的equals方法进行的是基于内存地址的比较,而不是基于内容的比较。
默认行为不符合编程的需要,所以在自定义类中需要重写equals方法,使得其基于内容来比较。
当然,这也告诉我们这样一件事情,判断对象的不同引用是否指向同一个对象有两种方法:①使用“==”;②调用超类的equls方法(只能是子类的内部)。
tips: 有一个问题值得注意:如果在类的外部(比如main方法中),能否通过一个对象调用已经被重写过的父类方法?? 如果不是类内部,而是外部调用,比如你例子中的main方法,答案是 |
在Java规范中,equals 方法在非空对象引用上实现相等关系,需要遵循以下几个原则:
①、自反性:对于任何的非null引用x,x.equals(x)应该返回true。
②、对称性:对于任何的非null引用x和y,当且仅当y.equals(x)返回true的时候,x.equals(y)才能返回true。
③、传递性:对于任何的非null引用x、y和z,如果x.equals(y)为true,且y.equals(z)为true,那么x.equals(z)也应该返回true。
④、一致性:对于任何非空引用值 x 和 y,如果对象中用于等价比较的信息没有改变,那么无论调用x.equals(y)多少次,返回的结果应该保持一致,要么一直是true,要么一直是false。
⑤、对于任何非空引用值 x,x.equals(null)应该返回false。
注意:一般来讲当重写equals方法以后都需要重写hashCode方法,使得相同的对象必须有相同的hashcode值(相同的hashcode值不一定是相同的对象)
在java中进行比较,我们需要根据比较的类型来选择合适的比较方式
1、对象域,使用equals方法。自定义类一般需要重写此方法。
2、类型安全的枚举,使用equals或== 。
3、可能为null的对象域 : 使用 == 或 equals 。( 比如:if(obj != null && obj.equels(o)){//...} )
4、数组域:使用Arrays.equals。
5、所有原始数据类型(非包装类型): 使用== 。
6、除了Float和Double外的包装类型,使用 == 或 equals。
7、Float包装类型,使用equals。(实际上,equals底层使用Float.foatToIntBits转换成int类型,然后使用== )。
8、Double包装类型:使用equals。(实际上,equals底层使用Double.doubleToLongBit转换成long类型,然后使用==)。
至于7)、8)为什么需要进行转换,我们可以参考他们相应封装类的equals()方法,下面的是Float类的:
public boolean equals(Object obj) {
return (obj instanceof Float)
&& (floatToIntBits(((Float)obj).value) == floatToIntBits(value));
}
下面是一组测试代码:
public static void main(String[] args){
System.out.println("\n-------int---------");
Integer I1 = 10, I2 = 10;
int i3 = 10;
System.out.println("I1 == I2: " + (I1 == I2));
System.out.println("I1 == i3: " + (I1 == i3)); System.out.println("\n-------float---------");
Float F1 = 2f, F2 = 2f;
System.out.println("F1 == F2: " + (F1==F2));
System.out.println("F1.equals(F2): " + F1.equals(F2)); float f3 = 2f, f4 = 2f;
System.out.println("f3 == f4: " + (f3 == f4));
System.out.println("F1 == f3: " + (F1 == f3)); System.out.println("\n-------double---------");
Double D1 = 12.5, D2 = 12.5;
System.out.println("D1 == D2:" + (D1==D2));
System.out.println("D1.equals(D2): " + D1.equals(D2)); double d3 = 12.5, d4 = 12.5;
System.out.println("d3 == d4: " + (d3==d4));
System.out.println("D1 == d3: " + (D1 == d3));
}
运行结果:
3、Object对象的两大方法(hashCode-equals)总结的更多相关文章
- JSON对象的两个方法
JSON对象有两个方法,stringify()和parse(). 最简单的方法,这两个方法分别用于吧JavaScript对象序列化为JSON字符串和把JSON字符串解析为原生JavaScript值. ...
- 读取xml文件转成List<T>对象的两种方法(附源码)
读取xml文件转成List<T>对象的两种方法(附源码) 读取xml文件,是项目中经常要用到的,所以就总结一下,最近项目中用到的读取xml文件并且转成List<T>对象的方法, ...
- 取xml文件转成List<T>对象的两种方法
读取xml文件转成List<T>对象的两种方法(附源码) 读取xml文件转成List<T>对象的两种方法(附源码) 读取xml文件,是项目中经常要用到的,所以就总结一下,最 ...
- Android中Intent传递对象的两种方法(Serializable,Parcelable)
今天要给大家讲一下Android中 Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object);另一种是 Bundle.putP ...
- 在Delphi中使用C++对象(两种方法,但都要改造C++提供的DLL)
Delphi是市场上最好的RAD工具,但是现在C++占据着主导地位,有时针对一个问题很难找到Delphi或Pascal的解决方案.可是却可能找到了一个相关的C++类.本文描述几种在Delphi代码中使 ...
- Intent传递对象的两种方法(Serializable,Parcelable) (转)
今天讲一下Android中Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object);另一种是Bundle.putParcela ...
- [转]Android中Intent传递对象的两种方法(Serializable,Parcelable)
http://blog.csdn.net/xyz_lmn/article/details/5908355 今天要给大家讲一下Android中Intent中如何传递对象,就我目前所知道的有两种方法,一种 ...
- Android高手进阶教程(十七)之---Android中Intent传递对象的两种方法(Serializable,Parcelable)!
[转][原文] 大家好,好久不见,今天要给大家讲一下Android中Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object); ...
- Intent传递对象的两种方法
Android为intent提供了两种传递对象参数类型的方法 分别需要使实体类实现Serializable接口.Parcelable接口 首先我们要知道,传递对象,需要先将对象序列化 一.那么为什么要 ...
随机推荐
- unity 协同
void Update () { if(Input .GetKeyDown (KeyCode .W )) { StartCoroutine ("Test"); } } IEnume ...
- android 通过AlarmManager实现守护进程
场景:在app崩溃或手动退出或静默安装后能够自动重启应用activity 前提:得到系统签名 platform.pk8.platform.x509.pem及signapk.jar 三个文件缺一不可(系 ...
- Jenkins-测试自动化环境搭建(Python+RobotFramework+selenium)
下载插件: Python:https://wiki.jenkins-ci.org/display/JENKINS/Python+Plugin RobotFramework:https://wiki.j ...
- 《我是IT小小鸟》读书笔记
转眼间,大学的第二学期悄悄来临了,老师给我们布置了一道原本我以为很无趣的题目----写<我是IT的读书笔记>,但是我读了<我是IT小小鸟>这本书后,令我受益匪浅:五个人,每个人 ...
- Mybatis代码调试问题总结(一)
问题: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): 原因排查: 1.检查map ...
- Codeforces Round #281 (Div. 2)
题目链接:http://codeforces.com/contest/493 A. Vasya and Football Vasya has started watching football gam ...
- __int64 与long long 的区别 分类: Brush Mode 2014-08-14 10:22 64人阅读 评论(0) 收藏
//为了和DSP兼容,TSint64和TUint64设置成TSint40和TUint40一样的数 //结果VC中还是认为是32位的,显然不合适 //typedef signed long int ...
- [百度空间] [原]DLL导出实例化的模板类
因为模板是在编译的时候根据模板参数实例化的,实例化之后就像一个普通的类(函数),这样才有对应的二进制代码;否则,没有模板参数,那么编译器就不知道怎么生成代码,所以生成的DLL就没有办法导出模板了.但是 ...
- 利用URLRewriter.dll 实现ASP.NET实现伪静态
大家一定经常在网络上看到很多网站的地址后缀都是用XX.HTML或者XX.ASPX等类似静态文件的标示来操作的吧,那么大家有怀疑过他真的是一个一个的静态生成的文件么,静态文件的生成的优缺有好有坏,对于访 ...
- 用vs2010 编写C语言程序,VS2010 C++编译报错LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏
编译mongodb-src-r2.2.2出现以下问题 LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 这个是由于日志文件引起的,可以将 项目\ ...