Java中 “==”、“equals()”、“hashCode()”

“==”

首先要讲下Java中的数据类型,分为俩类

基本数据类型(或者叫值类型、也叫原始数据类型),比如byte、int、double、boolean等,他们之间的比较就是使用“==”,这时候对比的是他们的值是否相等

int a = 10;

int b = 10;

System.out.print("a==b? " + (a == b));

//输出结果 a==b? true

引用数据类型,比如数组、类、接口等,这些数据直接使用“==”的话,进行比对的是其引用地址是否相同(这里对于String的比较后面再分析)

Integer aObj = new Integer(10);

Integer bObj = new Integer(10);

System.out.print("aObj==bObj? "+(aObj == bObj));

//输出结果 aObj==bObj? false

下面我们对“==”比较的一些情况进行分析,大家都看到了,我们用到了Integer,有必要跟大家说一下这个Integer是什么,这就要涉及到Java中的另一个概念了,包装类,每中基本数据类型都会对应有一个包装类,为了让基本数据类型也能满足万事万物皆对象嘛,其实包装类的出现对我们的很多操作都方便了。说到它那就得说它的2个概念,封箱和拆箱,简单解释就是,将基本数据类型封箱成对应的包装类,拆箱就是将包装类转换成对应的基本类型。

说了这么个概念,那到底对我们理解“==”有什么用呢?下面看下基本类型与包装类之间的相互比较的结果:

Integer aObj = new Integer(10);

Integer bObj = 100;

Integer cObj = 100;

int a = 10;

int b = 100;

System.out.println("aObj==a? " + (aObj == a)); //true

System.out.println("bObj==cObj? " + (bObj == cObj)); //true

System.out.println("bObj==b? " + (bObj == b)); //true 与第一个含义相同


对于上面的结果分析:

第一个 aObj == a 为true,那是因为基本数据类型与对应的包装类对象进行“==”比较的时候,包装类型会进行自动拆箱操作,拆箱成基本数据类型,所以最终比较的还是他们的值。

第二个 bObj == cObj 为true,这其中的原由要牵扯到Java编译,Java在编译的时候会对包装类型赋值基本数据转换成Integer.valueOf(基本数据); 也就是说  Integer bObj = 100;在class文件里面的含义就变成了 Integer bObj = Integer.valueOf(100);大家可以点进去看下valueOf的源码:

Integer.valueOf方法源码

通过源码可知,对于-128到127之间的数,Java会进行缓存,Integer bObj = 100;时,会将100进行缓存,下次再写Integer cObj = 100;时,就会直接从缓存中取,就不会new了。所以这2个对象的引用地址都是指向第一次创建的那个100的对象地址。

总结:“==”对于基本数据类型进行比较的就是他们的值是否相等,而对于引用类型进行比较的就是对象在内存地址的值,而我们知道Java中对象的创建是存放在中的,而对象存放的地址是存储在中,所以这个比较也就是对比栈中的值是否相等。


“equals”

这个方法是Object上帝类中的,我们直接去看看它长什么样子

Object类中的equals方法

我们可以看出,这个和上面讲的 “==” 其实是一个意思,所以当我们没有对equals进行重写的时候,也就是使用的是Object类中的equals方法的时候,其含义与“==”对比一样。

那么问题来了,既然是一样,为何还要多一个存在呢???其实这不是多,因为我们知道单纯的“==”对比是不能满足我们的对比需求的,所以我们一般都会对equals进行重写。

而提到equals,Java规范中对其有很多的规定,但是有一点我们必须注意的是,重写equals的时候必须要重写hashCode方法,给出的理由是 为了维持hashCode的一种约定,相同的对象必须要有相同的hashCode值,但是我们先分析下hashCode这个方法的实际作用我们再来讲equals和hashCode之间的关联,因为这里要分2种情况,并不是Java规范中那么硬性规定他们必须关联,看了他的作用之后你也就知道他们什么时候该一起重写,什么时候可以不管hashCode。

那么我们这时候就得说下什么是hashCode方法的作用了,hashCode方法的作用是获取哈希码,也叫做散列码;实际上就是一个int整数,该哈希码的作用就是确定对象在哈希表中的索引位置,这里出现的散列表概念我们就不展开了,一会也说不明白,大家只要知道大概知道Java中的散列表类主要是指集合,比如HashMap、HashTable、HashSet等,而哈希码只有在这些类中才会起作用,其他情况下就无用了,下面稍微概括一下哈希码在散列表中是如何起作用的:

我们都知道,散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。这其中就利用到了哈希码! 散列表的本质是通过数组实现的。当我们要获取散列表中的某个“值”时,实际上是要获取数组中的某个位置的元素。而数组的位置,就是通过“键”来获取的;更进一步说,数组的位置,是通过“键”对应的哈希码计算得到的。这个如果去详细了解集合的时候会讲到的。

接下来有了上面的理解,那么我们就可以分2部讲equals重写了

第一种 不会创建“类对应的散列表”

这里所说的“不会创建类对应的散列表”是说:我们不会在HashSet, Hashtable, HashMap等等这些本质是散列表的数据结构中,用到该类。在这种情况下,该类的“hashCode() 和 equals() ”没有半毛钱关系的!这种情况下,equals() 用来比较该类的两个对象是否相等。而hashCode() 则根本没有任何作用,所以,不用重写hashCode()。

第二种 会创建“类对应的散列表”

这就跟上面的相反了,类会用在集合里面,这时候该类的“hashCode() 和 equals() ”是有关系的:

        1)、如果两个对象相等,那么它们的hashCode()值一定相同。

              这里的相等是指,通过equals()比较两个对象时返回true。

        2)、如果两个对象hashCode()相等,它们并不一定相等。

因为在散列表中,hashCode()相等,即两个键值对的哈希值相等。然而哈希值相等,并不一定能得出键值对相等。补充说一句:“两个不同的键值对,哈希值相等”,这就是哈希冲突。

此外,在这种情况下。若要判断两个对象是否相等,除了要覆盖equals()之外,也要覆盖hashCode()函数。否则,equals()无效。

例如,创建Person类的HashSet集合,必须同时覆盖Person类的equals() 和 hashCode()方法。 如果单单只是覆盖equals()方法。我们会发现,equals()方法没有达到我们想要的效果。

总结:equals方法的使用,默认使用Object的equals方法,等价于使用“==”进行对比,而重写的话根据自己的逻辑去判断是否相等,注意后面涉及到的hashCode,虽然第一种情况下equals与hashCode方法没有关联,但是我们还是尽可能的去一起重写他们,因为你也没法说你写的这个类肯定不会用map去存储。

写得不好的地方多多海涵,有错误的地方欢迎留言区交流指正!

借鉴文章:https://www.cnblogs.com/skywang12345/p/3324958.html

编程不仅是一门技术!
编程更加是一门艺术!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容