hashCode与equals的区别与联系(经典)
- 格式:doc
- 大小:14.49 KB
- 文档页数:11
前言在Java语言中,equals()和hashCode()两个函数的使用是紧密配合的,你要是自己设计其中一个,就要设计另外一个。
在多数情况下,这两个函数是不用考虑的,直接使用它们的默认设计就可以了。
但是在一些情况下,这两个函数最好是自己设计,才能确保整个程序的正常运行。
最常见的是当一个对象被加入收集对象(collection object)时,这两个函数必须自己设计。
更细化的定义是:如果你想将一个对象A放入另一个收集对象B里,或者使用这个对象A为查找一个元对象在收集对象B里位置的钥匙,并支持是否容纳,删除收集对象B里的元对象这样的操作,那么,equals()和hashCode()函数必须开发者自己定义。
其他情况下,这两个函数是不需要定义的。
equals():它是用于进行两个对象的比较的,是对象内容的比较,当然也能用于进行对象参阅值的比较。
什么是对象参阅值的比较?就是两个参阅变量的值得比较,我们都知道参阅变量的值其实就是一个数字,这个数字可以看成是鉴别不同对象的代号。
两个对象参阅值的比较,就是两个数字的比较,两个代号的比较。
这种比较是默认的对象比较方式,在Object这个对象中,这种方式就已经设计好了。
所以你也不用自己来重写,浪费不必要的时间。
对象内容的比较才是设计equals()的真正目的,Java语言对equals()的要求如下,这些要求是必须遵循的。
否则,你就不该浪费时间:对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。
反射性:x.equals(x)必须返回是“true”。
类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。
还有一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。
今天下午研究了半天hashcode()和equals()方法,终于有了一点点的明白,写下来与大家分享1. 首先equals()和hashcode()这两个方法都是从object类中继承过来的。
equals()方法在object类中定义如下:public boolean equals(Object obj) {return (this == obj);}很明显是对两个对象的地址值进行的比较(即比较引用是否相同)。
但是我们必需清楚,当String 、Math、还有Integer、Double。
等这些封装类在使用equals()方法时,已经覆盖了object类的equals()方法。
比如在String类中如下:public boolean equals(Object anObject) {if (this == anObject) {return true;}if (anObject instanceof String) {String anotherString = (String)anObject;int n = count;if (n == anotherString.count) {char v1[] = value;char v2[] = anotherString.value;int i = offset;int j = anotherString.offset;while (n-- != 0) {if (v1[i++] != v2[j++])return false;}return true;}}return false;}很明显,这是进行的内容比较,而已经不再是地址的比较。
依次类推Double、Integer、Math。
等等这些类都是重写了equals()方法的,从而进行的是内容的比较。
当然了基本类型是进行值的比较,这个没有什么好说的。
我们还应该注意,Java语言对equals()的要求如下,这些要求是必须遵循的:• 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。
Java中的==,equals与hashCode的区别与联系(文章来源:北大青鸟成都锦江)一、概述1、概念∙== :该操作符生成的是一个boolean结果,它计算的是操作数的值之间的关系∙equals : Object 的实例方法,比较两个对象的content是否相同∙hashCode : Object 的native方法 , 获取对象的哈希值,用于确定该对象在哈希表中的索引位置,它实际上是一个int型整数二、关系操作符==1、操作数的值∙基本数据类型变量在Java中有八种基本数据类型:浮点型:float(4 byte), double(8 byte)整型:byte(1 byte), short(2 byte), int(4 byte) , long(8 byte)字符型: char(2 byte)布尔型: boolean(JVM规范没有明确规定其所占的空间大小,仅规定其只能够取字面值”true”和”false”)对于这八种基本数据类型的变量,变量直接存储的是“值”。
因此,在使用关系操作符== 来进行比较时,比较的就是“值”本身。
要注意的是,浮点型和整型都是有符号类型的(最高位仅用于表示正负,不参与计算【以byte 为例,其范围为-2^7 ~ 2^7 - 1,-0即-128】),而char是无符号类型的(所有位均参与计算,所以char类型取值范围为0~2^16-1)。
∙引用类型变量在Java中,引用类型的变量存储的并不是“值”本身,而是与其关联的对象在内存中的地址。
比如下面这行代码,String str1;这句话声明了一个引用类型的变量,此时它并没有和任何对象关联。
而通过new 来产生一个对象,并将这个对象和str1进行绑定:str1= new String("hello");那么str1 就指向了这个对象,此时引用变量str1中存储的是它指向的对象在内存中的存储地址,并不是“值”本身,也就是说并不是直接存储的字符串”hello”。
HashSet和HashMap一直都是JDK中最常用的两个类,HashSet要求不能存储相同的对象,HashMap要求不能存储相同的键。
那么Java运行时环境是如何判断HashSet中相同对象、HashMap中相同键的呢?当存储了“相同的东西”之后Java运行时环境又将如何来维护呢?在研究这个问题之前,首先说明一下JDK对equals(Object obj)和hashcode()这两个方法的定义和规范:在Java中任何一个对象都具备equals(Object obj)和hashcode()这两个方法,因为他们是在Object类中定义的。
equals(Object obj)方法用来判断两个对象是否“相同”,如果“相同”则返回true,否则返回false。
hashcode()方法返回一个int数,在Object类中的默认实现是“将该对象的内部地址转换成一个整数返回”。
接下来有两个个关于这两个方法的重要规范(我只是抽取了最重要的两个,其实不止两个):规范1:若重写equals(Object obj)方法,有必要重写hashcode()方法,确保通过equals(Object obj)方法判断结果为true的两个对象具备相等的hashcode()返回值。
说得简单点就是:“如果两个对象相同,那么他们的hashcode应该相等”。
不过请注意:这个只是规范,如果你非要写一个类让equals(Object obj)返回true而hashcode()返回两个不相等的值,编译和运行都是不会报错的。
不过这样违反了Java规范,程序也就埋下了BUG。
规范2:如果equals(Object obj)返回false,即两个对象“不相同”,并不要求对这两个对象调用hashcode()方法得到两个不相同的数。
说的简单点就是:“如果两个对象不相同,他们的hashcode可能相同”。
根据这两个规范,可以得到如下推论:1、如果两个对象equals,Java运行时环境会认为他们的hashcode一定相等。
(1)问题分析:考官主要想对hashCode()方法和equal()方法作用和效率上进行比较。
(2)核心答案讲解:equal()相等的两个对象他们的hashCode()肯定相等,也就用equal()对比可靠的。
hashCode()相等的两个对象他们的equal()不一定相等,也就hashCode()不可靠的。
对于需要量并且快速的对比的话如果都用equal()去显然效率太低,所以解决,每当需要对比的时候,首先用hashCode()去对比,如果hashCode()不一样,则表示这两个对象肯定不相等(也就不必再用equal()去再对比了),如果hashCode()相同,此时再对比他们的equal(),如果equal()也相同,则表示这两个对象真的相同了,这样既能提高了效率也保证了对比的正确性!(3)问题扩展:hashCode的重写:hashCode()和equal()一样都基本类Object里的方法,而和equal()一样,Object里hashCode()里面只返回当前对象的,如果这样的话,那么们相同的一个类,new两个对象,由于他们在内存里的不同,则他们的hashCode()不同,所以这显然不们想要的,所以们必须重写们类的hashCode()方法,即一个类,在hashCode()里面返回的一个hash值。
equals方法的作用:默认情况(没有覆盖equals方法)下equals方法都调用Object类的equals方法,而Object的equals方法主要用于判断对象的内存引用不同一个(不同一个对象);要类中覆盖了equals方法,那么就要根据具体的代码来确定equals方法的作用了,覆盖后一般都通过对象的内容否相等来判断对象否相等。
(4)结合中使用:equals方法默认的判断2个对象否相等的方法,在Object类里有实现,判断的2个对象的内存。
在hibernate中,不允许存在同类对象中有2个一样的实例。
equals方法和hashcode方法equals方法和hashcode方法是Java中两个重要的方法,它们在Java中的使用非常广泛,尤其是在集合框架中。
本文将从定义、作用、实现方式等方面详细介绍equals方法和hashcode方法。
一、equals方法1.定义equals方法是Object类中的一个方法,用于判断两个对象是否相等。
在Java中,所有的类都继承自Object类,因此所有的类都可以使用equals方法。
2.作用equals方法的作用是判断两个对象是否相等。
在Java中,相等的定义有两种:一种是引用相等,即两个对象的引用指向同一个内存地址;另一种是值相等,即两个对象的属性值相等。
equals方法默认使用引用相等进行比较,如果需要使用值相等进行比较,则需要在类中重写equals方法。
3.实现方式在Java中,重写equals方法需要满足以下条件:(1)自反性:对于任意的x,x.equals(x)应该返回true。
(2)对称性:对于任意的x和y,如果x.equals(y)返回true,则y.equals(x)也应该返回true。
(3)传递性:对于任意的x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,则x.equals(z)也应该返回true。
(4)一致性:对于任意的x和y,如果x.equals(y)返回true或false,则多次调用x.equals(y)应该返回相同的结果。
(5)非空性:对于任意的x,x.equals(null)应该返回false。
二、hashcode方法1.定义hashcode方法是Object类中的一个方法,用于返回对象的哈希码。
哈希码是一个整数,用于快速比较两个对象是否相等。
在Java中,哈希码通常用于集合框架中的散列表(HashMap、HashSet等)。
2.作用hashcode方法的作用是返回对象的哈希码。
哈希码可以用于快速比较两个对象是否相等,因为如果两个对象的哈希码不相等,则它们一定不相等。
ctf题解:equals和hashcode1. 背景介绍在进行ctf竞赛时,equals和hashcode是经常出现的一种题型,通常需要根据给出的代码和相关信息,来解答问题或解密密码。
equals 和hashcode是Java中用于比较对象和生成哈希码的两个方法,正确理解并使用它们对于解决ctf题目至关重要。
2. equals方法equals方法是用于比较两个对象的内容是否相同的方法,它的原型是```javapublic boolean equals(Object obj)```在重写equals方法时,需要注意以下几点:- 对象的比较顺序- 判空处理- 类型判断一个常见的equals方法的重写示例如下:```javaOverridepublic boolean equals(Object obj) {if (this == obj) {return true;}if (obj == null || getClass() != obj.getClass()) {return false;}// 比较对象的内容}```3. hashcode方法hashcode方法是用于生成对象的哈希码的方法,它的原型是```javapublic int hashCode()```在重写hashcode方法时,需要注意以下几点:- 哈希码相等对象不一定相等- 相等对象的哈希码一定相等- 哈希码尽可能分散一个常见的hashcode方法的重写示例如下:```javaOverridepublic int hashCode() {int result = // 根据对象的属性计算哈希码return result;}```4. ctf题目解析在ctf竞赛中,equals和hashcode题目常常涉及到对给定对象的equals和hashcode方法进行分析和求解。
参赛者需要根据给出的代码和相关信息,来判断两个对象是否相等或计算出其哈希码。
Java中的equals()和hashCode()方法是非常重要的方法,它们对于对象的比较和哈希值的计算起着至关重要的作用。
在使用Java开发中,我们经常需要重写这两个方法来确保对象的正确比较和哈希值的正确计算。
本文将介绍为什么需要重写equals()和hashCode()方法,以及如何正确地实现这两个方法。
1. 为什么需要重写equals()和hashCode()方法在Java中,所有的类都继承自Object类,而Object类中的equals()方法是用来比较对象的引用是否相等的,而hashCode()方法是用来返回对象的哈希值的。
在实际开发中,我们通常需要比较对象的内容是否相等而不是引用是否相等,同时也需要正确地计算哈希值以便于在集合中高效地查找对象。
2. equals()方法的重写实现equals()方法的重写时,通常需要遵循以下几个原则:2.1 使用instanceof关键字来判断是否为同一类型的对象。
2.2 对传入的参数进行null判断,并且判断是否为同一对象。
2.3 使用强制类型转换将Object类型转换为对应的类型,然后比较对象的内容是否相等。
我们有一个Person类,需要重写equals()方法来比较两个Person对象的内容是否相等:```javaOverridepublic boolean equals(Object obj) {if (this == obj) {return true;}if (obj == null || getClass() != obj.getClass()) {return false;}Person person = (Person) obj;return Objects.equals(name, )Objects.equals(age, person.age);}```3. hashCode()方法的重写实现hashCode()方法的重写时,通常需要遵循以下几个原则:3.1 使用一些非零的常数,如31等作为乘数。
equalsandhashcode注解equals和hashCode是Java中两个重要的方法,用于处理对象的相等性。
在Java中,用于比较对象相等性的最常用方法是使用equals方法。
而hashCode方法则用于获取一个对象的哈希码,它是一个用于快速查找对象的整数值。
equals方法的定义是用于比较两个对象是否相等。
在默认情况下,Java中的equals方法比较的是两个对象的引用是否相等。
这意味着如果两个对象的引用指向同一个内存地址,那么它们被认为是相等的。
但是在很多情况下,我们需要自定义equals方法的实现,以便根据对象的值来比较对象的相等性。
为了实现这一点,我们需要重写equals方法。
在重写equals方法时,需要遵循以下几个原则:1. 自反性:一个对象必须与自身相等。
即对于任意非空对象x,x.equals(x)应该返回true。
2. 对称性:对于任意非空对象x和y,如果x.equals(y)返回true,那么y.equals(x)也应该返回true。
3. 传递性:对于任意非空对象x、y和z,如果x.equals(y)返回true,并且y.equals(z)返回true,那么x.equals(z)也应该返回true。
4. 一致性:对于任意非空对象x和y,如果对象的值没有发生变化,那么多次调用x.equals(y)应该始终返回同样的结果。
5. 非空性:对于任意非空对象x,x.equals(null)应该返回false。
除了重写equals方法外,还需要重写hashCode方法。
hashCode方法返回对象的哈希码,它是一个用于快速查找对象的整数值。
在Java中,很多集合类如HashSet和HashMap使用对象的hashCode来确定对象在数据结构中的位置。
在重写hashCode方法时,需要遵循以下原则:1. 一致性:在对象的生命周期内,只要对象的值没有发生变化,那么多次调用hashCode方法应该始终返回同样的结果。
equals和hashcode方法嘿,咱今儿就来唠唠这 equals 和 hashcode 方法。
你说这 equals 方法啊,就好比是一个超级侦探,专门负责判断两个东西是不是真的一模一样。
它可精细着呢,能从里到外仔细对比,不放过任何一个小细节。
比如说有两个苹果,它得看看颜色是不是一样红,形状是不是一样圆,有没有斑点啥的,只有完全一样,它才会说“嘿,这俩确实相等”。
那这 hashcode 方法又是啥呢?它就像是给每个东西一个独特的标签。
就像每个人都有自己的身份证号一样,通过这个标签能快速找到对应的东西。
而且啊,它得尽量让不同的东西有不同的标签,不然不就乱套啦?咱来打个比方吧,想象一下图书馆里的书。
每本书都有自己的书名、作者、内容这些特点,这就像是 equals 方法要去比较的东西。
而每本书也都有一个独一无二的编码,这就是 hashcode 方法给它的标记。
工作人员根据这个编码就能快速找到那本书,多方便呀!在编程里,要是咱只重 equals 方法而忽略了 hashcode 方法,那不就像只知道这个人长啥样,却不知道他住哪儿一样,找起来得多费劲呀!反过来,要是只关注 hashcode 方法,那可能会把完全不一样的东西当成一样的,那不就闹笑话啦?你想想看,如果在一个集合里,两个明明不一样的东西,因为hashcode 方法出了问题被当成一样的,那不乱套了吗?就好像把猫和狗当成同一种动物,这多荒唐呀!所以呀,这 equals 和 hashcode 方法可得好好配合。
它们就像一对好搭档,一个负责精确判断,一个负责快速定位。
只有它们齐心协力,咱写的程序才能顺顺利利地运行,不出岔子。
咱在写代码的时候,可不能随便对待这俩方法。
得认真考虑它们的实现,要让它们符合实际需求,别整出些奇奇怪怪的结果来。
这就跟咱过日子一样,得认真对待每一件事,才能过得舒坦,不是吗?你说,要是没有这两个方法,编程得变得多混乱呀!它们就像是编程世界里的秩序维护者,让一切都有条有理。
详解hashCode()和equals()的本质区别和联系在学习java,根据视频做实例的过程中,对equals和hashcode两个⽅法理解稍微深刻⼀点,主要是它们两个很容易混淆,容易出错,⾃⼰⼜通过⽹上的资料学习,和⼤家分享equals()⽅法equals是Object类提供的⽅法之⼀,众所周知,每⼀个java类都继承⾃Object类,所以说每⼀个对象都有equals这个⽅法。
⽽我们在⽤这个⽅法时却⼀般都重写这个⽅法,why?先看⼀个Object类中equals()⽅法的源代码:public boolean equals(Object obj) {return (this == obj);}从这个⽅法中可以看出,只有当⼀个实例等于它本⾝的时候,equals()才会返回true值。
通俗地说,此时⽐较的是两个引⽤是否指向内存中的同⼀个对象,也可以称做是否实例相等。
⽽我们在使⽤equals()来⽐较两个指向值对象的引⽤的时候,往往希望知道它们逻辑上是否相等,⽽不是它们是否指向同⼀个对象——这就是我们通常重写这个⽅法的原因。
Strings1 = new String(“kvill”),String s2 = new String(“kvill”);s1.equals(s2)为ture,说明String类中已经重写了equals()⽅法,如果不重写equals()⽅法,那么s1.equals(s2)默认⽐较两个对象所指向的内存地址是否相同,返回值必然为false。
当然接下来我们要改写equals()⽅法,必须要遵守通⽤约定。
来⾃ng.Object的规范,equals⽅法实现了等价关系,以下是要求遵循的5点:1.⾃反性:对于任意的引⽤值x,x.equals(x)⼀定为true。
2.对称性:对于任意的引⽤值x 和 y,当x.equals(y)返回true时,y.equals(x)也⼀定返回true。
3.传递性:对于任意的引⽤值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也⼀定返回true。
HashMap中为啥要重写hashcode和equals⽅法1. equals⽅法如果使⽤==判断俩个对象是否相等,这个只是从地址看是否相等,⽽与我们的需求是不符合的。
即使俩个对象地址是不同的,如果它的属性是相同的,那么可判定这俩个对象相等。
未重写equals⽅法:public class Person {public static void main(String[] args) {Person p1 = new Person();Person p2 = new Person();System.out.println(p1.equals(p2));}public int no;public String name;}运⾏截图:重写equals⽅法后:public class Person {public static void main(String[] args) {Person p1 = new Person();Person p2 = new Person();System.out.println(p1.equals(p2));}public int no;public String name;@Overridepublic boolean equals(Object o) {if (this == o) {return true;}if (o == null || getClass() != o.getClass()) {return false;}Person person = (Person) o;if (no != person.no) {return false;}return name != null ? name.equals() : == null;}}运⾏截图:2. hashCode⽅法由于在hashMap中在put时,散列函数根据它的哈希值找到对应的位置,如果该位置有原素,⾸先会使⽤hashCode⽅法判断,如果没有重写hashCode⽅法,那么即使俩个对象属性相同hashCode⽅法也会认为他们是不同的元素,⼜因为Set是不可以有重复的,所以这会产⽣⽭盾,那么就需要重写hashCode⽅法。
为什么重写equals时必须重写hashCode⽅法?hashCode()与 equals()⾯试官可能会问你:“你重写过hashcode和equals么,为什么重写equals时必须重写hashCode⽅法?”1)hashCode()介绍:hashCode()的作⽤是获取哈希码,也称为散列码;它实际上是返回⼀个 int 整数。
这个哈希码的作⽤是确定该对象在哈希表中的索引位置。
hashCode()定义在 JDK 的Object类中,这就意味着 Java 中的任何类都包含有hashCode()函数。
另外需要注意的是:Object的 hashcode ⽅法是本地⽅法,也就是⽤ c 语⾔或 c++ 实现的,该⽅法通常⽤来将对象的内存地址转换为整数之后返回。
public native int hashCode();散列表存储的是键值对(key-value),它的特点是:能根据“键”快速的检索出对应的“值”。
这其中就利⽤到了散列码!(可以快速找到所需要的对象)2)为什么要有 hashCode?我们以“HashSet如何检查重复”为例⼦来说明为什么要有 hashCode?当你把对象加⼊HashSet时,HashSet会先计算对象的 hashcode 值来判断对象加⼊的位置,同时也会与其他已经加⼊的对象的 hashcode 值作⽐较,如果没有相符的 hashcode,HashSet会假设对象没有重复出现。
但是如果发现有相同 hashcode 值的对象,这时会调⽤ equals()⽅法来检查 hashcode 相等的对象是否真的相同。
如果两者相同,HashSet就不会让其加⼊操作成功。
如果不同的话,就会重新散列到其他位置。
(摘⾃我的 Java 启蒙书《Head fist java》第⼆版)。
这样我们就⼤⼤减少了 equals 的次数,相应就⼤⼤提⾼了执⾏速度。
3)为什么重写equals时必须重写hashCode⽅法?如果两个对象相等,则 hashcode ⼀定也是相同的。
Java基础知识点面试专题1、java中==和equals和hashCode的区别1)==若是基本数据类型比较,是比较值,若是引用类型,则比较的是他们在内存中的存放地址。
对象是存放在堆中,栈中存放的对象的引用,所以==是对栈中的值进行比较,若返回true代表变量的内存地址相等;2)equals是Object类中的方法,Object类的equals方法用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象)。
若是类中覆盖了equals方法,就要根据具体代码来确定,一般覆盖后都是通过对象的内容是否相等来判断对象是否相等。
3)hashCode()计算出对象实例的哈希码,在对象进行散列时作为key存入。
之所以有hashCode方法,因为在批量的对象比较中,hashCode比较要比equals快。
在添加新元素时,先调用这个元素的hashCode方法,一下子能定位到它应该旋转的物理位置,若该位置没有元素,可直接存储;若该位置有元素,就调用它的equals方法与新元素进行比较,若相同则不存,不相同,就放到该位置的链表末端。
4)equals与hashCode方法关系:hashCode()是一个本地方法,实现是根据本地机器上关的。
equals()相等的对象,hashCode()也一定相等;hashCode()不等,equals()一定也不等;hashCode()相等,equals()可能相等,也可能不等。
所以在重写equals(Object obj)方法,有必要重写hashCode()方法,确保通过equals(Object obj)方法判断结果为true的两个对象具备相等的hashCode()返回值。
5)equals与==的关系:Integer b1 = 127;在java编译时被编译成Integer b1 = Integer.valueOf(127);对于-128到127之间的Integer值,用的是原生数据类型int,会在内存里供重用,也就是这之间的Integer值进行==比较时,只是进行int原生数据类型的数值进行比较。
equals和HashCode深入理解以及Hash算法原理1.深入理解equals():提醒:Object类中的equals方法和“==”是一样的,没有区别,即俩个对象的比较是比较他们的栈内存中存储的内存地址。
而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同”,他们比较的是值是不是相等。
所以,当自己创建类时,自动继承了Object的equals方法,要想实现不同的等于比较,必须重写equals方法。
我们看下面这个例子:package cn.galc.test;public class TestEquals {public static void main(String[] args) {/*** 这里使用构造方法Cat()在堆内存里面new出了两只猫,* 这两只猫的color,weight,height都是一样的,* 但c1和c2却永远不会相等,这是因为c1和c2分别为堆内存里面两只猫的引用对象,* 里面装着可以找到这两只猫的地址,但由于两只猫在堆内存里面存储在两个不同的空间里面,* 所以c1和c2分别装着不同的地址,因此c1和c2永远不会相等。
*/Cat c1 = new Cat(1, 1, 1);Cat c2 = new Cat(1, 1, 1);System.out.println("c1==c2的结果是:"+(c1==c2));//falseSystem.out.println("c1.equals(c2)的结果是:"+c1.equals(c2));//false}}class Cat {int color, weight, height;public Cat(int color, int weight, int height) {this.color = color;this.weight = weight;this.height = height;}}画出内存分析图分析c1和c2比较的结果,当执行Cat c1 = new Cat(1,1,1); Cat c2 = new Cat(1,1,1); 之后内存之中布局如下图:由此我们看出,当我们new一个对象时,将在内存里加载一份它自己的内存,而不是共用!对于static修饰的变量和方法则保存在方法区中,只加载一次,不会再多copy一份内存。
java中equals,hashcode和==的区别1、==java中的数据类型,可分为两类:1.基本数据类型,也称原始数据类型byte,short,char,int,long,float,double,boolean 他们之间的⽐较,应⽤双等号(==),⽐较的是他们的值。
2.引⽤类型(类、接⼝、数组)当他们⽤(==)进⾏⽐较的时候,⽐较的是他们在内存中的存放地址,所以,除⾮是同⼀个new出来的对象,他们的⽐较后的结果为true,否则⽐较后结果为false。
对象是放在堆中的,栈中存放的是对象的引⽤(地址)。
由此可见'=='是对栈中的值进⾏⽐较的。
如果要⽐较堆中对象的内容是否相同,那么就要重写equals⽅法了。
例:1. public static void main(String[] args) {2.3. int int1 = 12;4. int int2 = 12;5. Integer Integer1 = new Integer(12);6. Integer Integer2 = new Integer(12);7. Integer Integer3 = new Integer(127);8.9. Integer a1 = 127;10. Integer b1 = 127;11.12. Integer a = 128;13. Integer b = 128;14.15. String s1 = "str";16. String s2 = "str";17. String str1 = new String("str");18. String str2 = new String("str");19.20. System.out.println("int1==int2:" + (int1 == int2));21. System.out.println("int1==Integer1:" + (int1 == Integer1));22. System.out.println("Integer1==Integer2:" + (Integer1 == Integer2));23. System.out.println("Integer3==b1:" + (Integer3 == b1));24. System.out.println("a1==b1:" + (a1 == b1));25. System.out.println("a==b:" + (a == b));26.27.28. System.out.println("s1==s2:" + (s1 == s2));29. System.out.println("s1==str1:" + (s1 == str1));30. System.out.println("str1==str2:" + (str1 == str2));31.32. }输出结果:int1==int2:trueint1==Integer1:true //Integer会⾃动拆箱为int,所以为trueInteger1==Integer2:false//不同对象,在内存存放地址不同,所以为falseInteger3==b1:false//Integer3指向new的对象地址,b1指向缓存中127地址,地址不同,所以为falsea1==b1:truea==b:falses1==s2:trues1==str1:falsestr1==str2:falseInteger b1 = 127;java在编译的时候,被翻译成-> Integer b1 = Integer.valueOf(127);1. public static Integer valueOf(int i) {2. assert IntegerCache.high >= 127;3. if (i >= IntegerCache.low && i <= IntegerCache.high)4. return IntegerCache.cache[i + (-IntegerCache.low)];5. return new Integer(i);6. }看⼀下源码⼤家都会明⽩,对于-128到127之间的数,会进⾏缓存,Integer b1 = 127时,会将127进⾏缓存,下次再写Integer i6 = 127时,就会直接从缓存中取,就不会new了。
如果函数返回类型不同,子类的同名函数不能继承父类的同名函数c++ 如果返回值类型是基本数据类型,必须相同,不然编译不通过。
如果返回值类型是类类型,可以不相同hashcode方法浅析有许多人学了很长时间的Java,但一直不明白hashCode方法的作用,我来解释一下吧。
首先,想要明白hashCode的作用,你必须要先知道Java中的集合。
总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set。
你知道它们的区别吗?前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。
那么这里就有一个比较严重的问题了:要想保证元素不重复,可两个元素是否重复应该依据什么来判断呢?这就是Object.equals方法了。
但是,如果每增加一个元素就检查一次,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了。
也就是说,如果集合中现在已经有1000个元素,那么第1001个元素加入集合时,它就要调用1000次equals方法。
这显然会大大降低效率。
于是,Java采用了哈希表的原理。
哈希(Hash)实际上是个人名,由于他提出一哈希算法的概念,所以就以他的名字命名了。
哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。
如果详细讲解哈希算法,那需要更多的文章篇幅,我在这里就不介绍了。
初学者可以这样理解,hashCode方法实际上返回的就是对象存储的物理地址(实际可能并不是)。
这样一来,当集合要添加新的元素时,先调用这个元素的hashCode 方法,就一下子能定位到它应该放置的物理位置上。
如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。
所以这里存在一个冲突解决的问题。
这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次。
JAVA中equals⽅法与hashCode⽅法学习1,equals⽅法的⽐较与 == 的区别是什么?为什么需要重写equals⽅法?2,为什么说重写了equals⽅法最好重写hashCode⽅法?该问题在参考博⽂⾥⾯有⼀个实例解释了原因。
3,如何重写equals⽅法和hashCode⽅法? ————————————————————————————————————————————————1,equals ⽅法在Object类中,⽽任何类都继承于Object类,因此任何类都有equals⽅法。
⽽Object类中的equals⽅法⽐较两个对象的原则是:两个对象是否在内存中同⼀个位置(与 == 的作⽤相同),并不是基于对象的特征来进⾏⽐较的,因此这也是为什么需要重写equals⽅法的原因。
⽐如说:表⽰⼈的 Person类,在现实⽣活中,只要两个⾝份证号码相同,就认为它代表的是同⼀个⼈。
那么,不管你 new 了⼏个Person对象,只要这⼏个Person对象的ID(⾝份证)属性相同,对象1.equals(对象2) 就应该返回true,⽽与对象1、对象2在内存中的位置⽆关!2,重写了equals为什么要重写hashCode呢?⽂中开头的参考博⽂中已经提到了⼀个原因。
也就是说,既然对象1.equals(对象2) 返回了true,即这两个对象实际上应该是同⼀个对象,那么应该存储到内存中相同的位置。
⽽hashCode就是⽤来计算对象放置的物理内在地址。
有关hashCode作⽤继承参考以下⽂章:3,这个要根据实际的需要来进⾏重写。
对于equals⽅法⽽⾔,有⼀个固定的模式,(this == obj obj==null ……)这不介绍了。
注意,可以使⽤Eclipse中的⽣成equals和hashCode⽅法。
(Source-->generate hashCode() and equals....)。
Java中equals⽅法和hashCode⽅法的关系equals()和hashCode()都是Object类中定义的⽅法,所有类都有这两个⽅法Object类中equals⽅法的代码如下:public boolean equals(Object obj) {return (this == obj);}当不对equals()重写时,默认是使⽤的是“==”进⾏对对象的地址进⾏⽐较,地址相同则返回true,如下MyObject a = new MyObject(123);MyObject b = new MyObject(123);a.equals(b);// a和b的内容是相同的,但是地址不同,所以equals返回值为false⾃定义的类实例进⾏内容⽐较时,需要重写equals()⽅法,⽽String等类已经重写了equals()⽅法。
hashCode()⽅法作⽤是计算对象的哈希值。
该⽅法⼀般使⽤场景是把对象保存在需要计算哈希值的类中(如HashMap,Hashtable,HashSet)。
MyObject a = new MyObject(123);MyObject b = new MyObject(123);a.equals(b);// 假设equals被重写为对123进⾏⽐较,返回trueMap<MyObject> mp = new hashMap<>();mp.add(a);mp.add(b);System.out.println(a.hashCode(),b.hashCode());// hashCode()⽅法没被重写,这⾥a和b的哈希值不同两个对象equals⽐较返回true,仍然可以同时存在hashMap中。
为了和equals⽅法保持⼀致--euqals返回true时,两个对象的hashcode⽅法返回值相同;两个对象的hashcode不同时,equals⽅法返回false。
hashCode与equals的区别与联系(经典)一、equals方法的作用1、默认情况(没有覆盖equals 方法)下equals方法都是调用Object类的equals方法,而Object的equals方法主要用于判断对象的内存地址引用是不是同一个地址(是不是同一个对象)。
2 、要是类中覆盖了equals方法,那么就要根据具体的代码来确定equals方法的作用了,覆盖后一般都是通过对象的内容是否相等来判断对象是否相等。
没有覆盖equals方法代码如下:[java] view plaincopy//学生类public class Student { private int age; private String name; public Student() { } public Student(int age, String name) { super(); this.age = age; = name; } public int getAge(){ return age; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public void setName(String name) { = name; } } 测试代码如下:[java] view plaincopyimport java.util.HashSet; importjava.util.LinkedList; import java.util.Set; public class EqualsTest { public static void main(String[]args) { LinkedList<Student> list = new LinkedList<Student>(); Set<Student> set = new HashSet<Student>(); Studentstu1 = new Student(3,"张三"); Student stu2 = new Student(3,"张三"); System.out.println("stu1 == stu2 : "+(stu1 == stu2));System.out.println("stu1.equals(stu2) :"+stu1.equals(stu2)); list.add(stu1);list.add(stu2); System.out.println("list size:"+ list.size()); set.add(stu1);set.add(stu2); System.out.println("set size:"+ set.size()); } } 运行结果:stu1 == stu2 : falsestu1.equals(stu2) : falselist size:2set size:2结果分析:Student类没有覆盖equals方法,stu1调用equals方法实际上调用的是Object的equals方法。
所以采用对象内存地址是否相等来判断对象是否相等。
因为是两个新对象所以对象的内存地址不相等,所以stu1.equals(stu2) 是false。
3、我们覆盖一下equals方法(age和name属性),让Student 类其通过判断对象的内容是否相等来确定对象是否相等。
覆盖后的Student类:[java] view plaincopy//学生类public class Student { private int age; private String name; public Student() { } publicStudent(int age, String name) { super();this.age = age; = name; } public int getAge() { return age; }public String getName() { return name; } public void setAge(int age) { this.age =age; } public void setName(String name){ = name; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj;if (age != other.age) return false;if (name == null) { if ( != null) return false; } else if (!name.equals()) return false; return true; } } 运行结果:stu1 == stu2 : falsestu1.equals(stu2) : truelist size:2set size:2结果分析:因为Student两个对象的age和name属性相等,而且又是通过覆盖equals方法来判断的,所示stu1.equals(stu2) 为true。
注意以上几次测试list和set的size都是2二、HashCode4、通过以上的代码运行,我们知道equals方法已经生效。
接下来我们在覆盖一下hashCode 方法(通过age和name属性来生成hashcode)并不覆盖equals方法,其中Hash码是通过age和name生成的。
覆盖hashcode后的Student类:[java] view plaincopy//学生类public class Student { private int age;private String name; public Student() { } public Student(int age, String name) { super(); this.age = age; = name; } public int getAge() { return age; }public String getName() { return name; } public void setAge(int age) { this.age =age; } public void setName(String name){ = name; } @Override public int hashCode() { final int prime = 31;int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 :name.hashCode()); return result; } } 运行结果:stu1 == stu2 : falsestu1.equals(stu2) : falselist size:2hashCode :775943hashCode :775943set size:2结果分析:我们并没有覆盖equals方法只覆盖了hashCode方法,两个对象虽然hashCode一样,但在将stu1和stu2放入set集合时由于equals方法比较的两个对象是false,所以就没有在比较两个对象的hashcode值。
5、我们覆盖一下equals方法和hashCode方法。
Student代码如下:[java] view plaincopy//学生类public class Student { private int age; private String name;public Student() { } public Student(int age, String name) { super(); this.age = age; = name; } public int getAge() { return age; } public String getName() { return name; }public void setAge(int age) { this.age =age; } public void setName(String name){ = name; } @Override public int hashCode() { final int prime = 31;int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 :name.hashCode());System.out.println("hashCode : "+ result); return result; } @Override public booleanequals(Object obj) { if (this == obj)return true; if (obj == null) return false; if (getClass() != obj.getClass())return false; Student other = (Student) obj;if (age != other.age) return false;if (name == null) { if ( != null) return false; } else if (!name.equals()) return false; return true; } }运行结果:stu1 == stu2 : falsestu1.equals(stu2) :truelist size:2hashCode :775943hashCode :775943set size:1结果分析:stu1和stu2通过equals方法比较相等,而且返回的hashCode值一样,所以放入set集合中时只放入了一个对象。