对象根类 Object
equals和hashcode最初定义
哈希算法也称为散列算法,是将数据依特定算法直接指定到一个(初学者:物理地址)地址上。
在object类中,hashcode()方法是本地方法,返回的是对象的引用(地址值),而object类中的equals()方法比较的也是两个对象的引用(地址值),如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了.
其中含有 equals()方法和hashcode()方法,前者比较首地址是否相等,后者计算此对象在内存中地址转换成的一个int值(可以就当做地址看)
所以对象之间的比较本来是比较首地址是否相等,如果相等那么hashcode一定相等,反之不行。
equals()方法不相等的两个对象,hashcode()有可能相等
equals和hashcode的演变重写
随着不同的对象不同的需求,每个对象重写这两个方法,现在基本被重写用来不同的内涵
‘==’
直观印象就是比较两个值是否相等
"=="
是用来比较两个变量(基本类型和对象类型)的值是否相等的, 如果两个变量是基本类型的,那很容易,
直接比较值就可以了。如果两个变量是对象类型的,那么它还是比较值,只是它比较的是这两个对象在栈中的引用
(即地址)。
对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见'=='是对栈中的值进行比较的。
如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。
equals
直观印象就是比较两个某某是否相等,比较模糊。
对象在堆内存的首地址,即用来比较两个引用变量是否指向同一个对象。
object类中的equals()方法比较的也是两个对象的地址值,如果equals()相等,说明两个对象地址值也相等,当然hashcode()也就相等了.
hashcode
这个是以人的名字命名的算法,本质是散列算法,就是计算对象在内存中地址
并且转换成的一个int值(可以就当做地址看)
举例:
public static void main(String[] args) {
Person p1= new Person();
Person p2= new Person();
//计算对象在内存中的地址并转换成一个int值
System.out.println("p1hashcode==="+t41.hashCode());//664740647
System.out.println("p2hashcode==="+t42.hashCode());//804564176
System.out.println(p1.equals(p2));//false 引用地址不相等
t42 = t41;
System.out.println(t41.equals(t42));//true 引用地址相等
//hashcode一致
System.out.println("p1hashcode==="+t41.hashCode());//664740647
System.out.println("p2hashcode==="+t42.hashCode());//664740647
}
八大基本类型和他们的关系
八大基本类型的比较用 == 是数值的比较 不能用equals
八大基本类型的比较用相等 ==
1、整型的byte、short、int、long;
2、字符型的char;
3、浮点型的float、double;
4、布尔型的boolean。
八大基本类型的包装类
String、Integer、Boolean、Double等这些类都重写了equals和hashCode方法,这两个方法是根据对象的内容来比较和计算hashCode的。(详细可以查看jdk下的String.java源代码),所以只要对象的基本类型值相同,那么hashcode就一定相同。
String和他们的关系
string中比较相等也是用equals()方法,不过是重写了Object类此方法,所以这里比较的是内容的比较。
public static void main(String[] args) {
String a = new String("str");
String b = new String("str");
System.out.println(a == b);//false 因为对象的内存地址不同
System.out.println(a.equals(b));//true 比较对象的内容
System.out.println(a.hashCode());//114225
System.out.println(b.hashCode());//114225
}
String s1,s2,s3 = "abc", s4 ="abc" ;
s3==s4是true(即使没有s3=s4这样一个赋值语句)
StringBuffer 和他们的关系
StringBuffer s1 = new StringBuffer("a");
StringBuffer s2 = new StringBuffer("a");
结果: s1.equals(s2) //是false
解释:
StringBuffer类中没有重新定义equals这个方法,因此这个方法就来自Object类,
而Object类中的equals方法是用来比较“地址”的,所以等于false.
Java中equals方法和“==”的区别:
equals 方法是 java.lang.Object 类的方法
(1)对于字符串变量来说
使用“==”和“equals()”方法比较字符串时,其比较方法不同。
“==”比较两个变量本身的值,即两个对象在内存中的首地址。
“equals()”比较字符串中所包含的内容是否相同。
- '==‘是用来比较两个变量(基本类型和对象类型)的值是否相等的, 如果两个变量是基本类型的,那很容易,直接比较值就可以了。如果两个变量是对象类型的,那么它还是比较值,只是它比较的是这两个对象在栈中的引用(即地址)。
对象是放在堆中的,栈中存放的是对象的引用(地址)。由此可见’'是对栈中的值进行比较的。如果要比较堆中对象的内容是否相同,那么就要重写equals方法了。 - Object类中的equals方法就是用’'来比较的,所以如果没有重写equals方法,equals和是等价的。
通常我们会重写equals方法,让equals比较两个对象的内容,而不是比较对象的引用(地址)因为往往我们觉得比较对象的内容是否相同比比较对象的引用(地址)更有意义。
(2)对于非字符串变量来说,"=="和"equals"方法的作用是相同的都是用来比较其
对象在堆内存的首地址,即用来比较两个引用变量是否指向同一个对象。
总之:
equals方法对于字符串来说是比较内容的,而对于非字符串来说是比较其指向的对象是否相同的。
== 比较符也是比较指向的对象是否相同的也就是对象在对内存中的的首地址。
String类中重新定义了equals这个方法,而且比较的是值,而不是地址。所以是true。