java==和equalse的区别是什么
这篇文章主要介绍“java==和equalse的区别是什么”,在日常操作中,相信很多人在java==和equalse的区别是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java==和equalse的区别是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
创新互联-专业网站定制、快速模板网站建设、高性价比南平网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式南平网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖南平地区。费用合理售后完善,十余年实体公司更值得信赖。
1.总的来说==和equalse 比较的都是地址值;
2.==在对比基本数据类型和包装类的常量池的时候,比较的是值
3.equalse是方法,只能作用于对象数据(Integer等封装类也是对象哈),默认也是比较地址值,但是大多数情况下我们是覆写equalse方法来对比其属性值是否一样;
4.但是equalse方法可以被重写。基本类型中封装类Integer和String的equalse方法都是被重写过的,所以比较的是值
5.Integer的常量池很好理解 -128 127,String也有常量池,我们字面创建String a=“xxx”这种都是进入常量池
String的常量池说明可以参考这篇文章: https://www.cnblogs.com/tongkey/p/8587060.html
分开讲述==和equalse
一、先说==,在比较不同数据的时候效果
1.基础数据类型:
比较的是他们的值是否相等,比如两个int类型的变量,比较的是变量的值是否一样。
2.引用数据类型:
比较的是引用的地址是否相同,比如说新建了两个User对象,比较的是两个User的地址是否一样。
3.基本类型的包装类问题
3.1包装类,通过new创建对象
基本类型的包装类 也算是对象,不管是否使用常量池,只要一方通过new创建对象,那就一定是比较的地址值
以Integer举例
不使用常量池:-128 127 public static void equalsTest(){ Integer A=new Integer(1); Integer B=new Integer(1);; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 输出结果为:A!=B 使用常量池 public static void equalsTest(){ Integer A=new Integer(128); Integer B=new Integer(128);; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 输出结果为:A!=B
3.2基本类型的包装类 不使用new创建对象的时候
以Integer举例
在-128 127的时候,会使用常量池数据,从而比较对象值;不使用常量池的时候,会比较地址值
使用常量池的时候-128 127 public static void equalsTest(){ Integer A=-127; Integer B=-127;; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 输出结果为:A=B 不使用常量池的时候,比较的是地址值 public static void equalsTest(){ Integer A=128; Integer B=128;; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 输出结果为:A!=B
3.3Integer的特殊情况 Integer在用==对比int类型的时候,无论何时都是对比的值
赋值128,没有使用到常量池 public static void equalsTest(){ Integer A=new Integer(128); int B=128; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 输出结果为:A=B 查看源码 发现 Integer只会对int作值的比较 /** * Compares this object to the specified object. The result is * {@code true} if and only if the argument is not * {@code null} and is an {@code Integer} object that * contains the same {@code int} value as this object. * * @param obj the object to compare with. * @return {@code true} if the objects are the same; * {@code false} otherwise. */ public boolean equals(Object obj) { if (obj instanceof Integer) { return value == ((Integer)obj).intValue(); } return false; }
3.4 String类型的使用常量池对比的也是值(绝大多数情况都是用到常量池)
我们通常使用String A="hello";这种方式创建的所有变量所有的都进了字符串常量池
这种创建方式都是会使用到常量池 public static void equalsTest(){ String A="hello"; String B="hello"; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 输出结果为: A=B 我们通常使用String A="hello";这种方式创建的所有变量所有的都进了字符串常量池 String类的final修饰的,以字面量的形式创建String变量时,jvm会在编译期间就把该字面量(“hello”)放到字符串常量池中,由Java程序启动的时候就已经加载到内存中了。这个字符串常量池的特点就是有且只有一份相同的字面量,如果有其它相同的字面量,jvm则返回这个字面量的引用,如果没有相同的字面量,则在字符串常量池创建这个字面量并返回它的引用
3.5 String类型不使用常量池的情况,比较的是地址值
public static void equalsTest(){ String A="hello"; String B=new String("hello");; if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 输出结果为:A!=B 通过new创建对象,使用的是新的对象,结果自然不相等 public static void equalsTest(){ String A="hello"; String B=new String("hello"); //B引用变为常量池的hello的引用 B=B.intern(); if(A==B){ System.out.println("A=B"); }else{ System.out.println("A!=B"); } } 输出结果为:A=B
二、equalse是方法,只能作用于对象数据(Integer等封装类也是对象哈),默认也是比较地址值
1.equalse方法默认还是比较地址值。但是可以被重写
在大多数Java类库中的类中 如基本类型中封装类Integer和String的equalse方法都是被重写过的,所以比较的是值
通常我们使用equalse都是自己覆写方法来对比对象内部的属性值是否相同
三、值相同的时候,hashcode不一定相同
结论:hashcode相同,值不一定相同,值相同hashCode一定相同(重写hashCode方法)
1. 为什么ashcode相同,值一定相同,值相同hashCode不一定相同
hashCode是所有java对象的固有方法,如果不重写的话,返回的实际上是该对象在jvm的堆上的内存地址,而不同对象的内存地址肯定不同,所以这个hashCode也就肯定不同了。如果重写了的话,由于采用的算法的问题,有可能导致两个不同对象的hashCode相同。
2.hashCode和equalse的关联关系
hashCode和equals两个方法是有语义关联的,它们需要满足:
A.equals(B)==true --> A.hashCode()==B.hashCode()
因此重写其中一个方法时也需要将另一个也重写。
3.HashCode方法重写需要满足规范
如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
3.1 hashCode的重写实现需要满足不变性,即一个object的hashCode不能前一会是1,过一会就变成2了。
3.2 hashCode的重写实现最好依赖于对象中的final属性,从而在对象初始化构造后就不再变化。一方面是jvm便于代码优化,可以缓存这个hashCode;另一方面,在使用hashMap或hashSet的场景中,如果使用的key的hashCode会变化,将会导致bug,比如放进去时key.hashCode()=1,等到要取出来时key.hashCode()=2了,就会取不出来原先的数据。
4.hashCode为什么会存在相同的情况
以hashSet举例,hashSet JDK1.8以前底层结构是数组+链表的形式,1.8之后是数组+链表+红黑树
以1.8举例:
在向hashSet集合中添加元素时,需要经过两个步骤
计算hashcode并与hashSet数组中的hashcode进行比较
如果有相同的hashcode,则对该hash的内容使用equals进行比较,如果不同则存入集合
因此相同的hashcode不一定有相同的值,但是如果值相同,那他的hashcode一定相同
4. 只要使用HashSet存储自定义类型的数据切记要重写equals和hashCode方法
到此,关于“java==和equalse的区别是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注创新互联网站,小编会继续努力为大家带来更多实用的文章!
文章名称:java==和equalse的区别是什么
本文URL:http://scyanting.com/article/psjpgc.html