微风·六·JAVA中“==”、hashcode、equals及字符串常量池的区别

vector线程安全的集合
hashset底层为hashmap

1 “==”和equals的区别是什么?

  • “= =”是运算符,如果是基本数据类型,比较是存储的值: int i = 100; int j = 100; i= =j;true
  • 若是引用数据类型,比较的是所指向对象的地址值:User user1 = new User(); User user2 = new User(); user1= =user2; false

1.1 “==”解释

“==”是运算符

  • ① 若相比对象是基本数据类型,则比较存储值是否相等;
  • ② 若相比是引用数据类型,则比较是所指向对象的地址值是否相等。

案例:

        final String str2 = "ab";//在字符串常量池中创建“ab”,并将地址值赋值给str2
        System.out.println(str2);
        final String str3 = "cd";//在字符串常量池中创建“cd”,并将地址值赋值给str3
        System.out.println(str3);
        String str6 = new String("abcd");//在堆中开辟地址空间,并把得到的地址值赋值给str6
        String str4 = str2+str3;//在字符串常量池中得到abcd的地址
        System.out.println(str4);

        String str5 = "abcd";//在字符串常量池中创建abcd时,发现已有,不用创建,就使用创建好的地址值
        System.out.println("str4 = str5 : " + (str4==str5));//true

        System.out.println("str6 = str5 : " + (str6==str5));//false

1.2 “equals”解释

equals是Object的方法,用来比较两个对象地址值是否相等。

源码如下(其底层仍是“==”):
在这里插入图片描述

案例:

        final String str2 = "ab";//在字符串常量池中创建“ab”,并将地址值赋值给str2
        System.out.println(str2);
        final String str3 = "cd";//在字符串常量池中创建“cd”,并将地址值赋值给str3
        System.out.println(str3);
        String str6 = new String("abcd");//在堆中开辟地址空间,并把得到的地址值赋值给str6
        String str4 = str2+str3;//在字符串常量池中得到abcd的地址
        System.out.println(str4);

        String str5 = "abcd";//在字符串常量池中创建abcd时,发现已有,不用创建,就使用创建好的地址值
        System.out.println("str4 = str5 : " + (str4==str5));//true

        System.out.println("str6 = str5 : " + (str6==str5));//false
        System.out.println(str6.equals(str4)); //true :String底层重写了equals比较的是对象的内容

1.3 注意点:equals不能比较基本数据类型

equals不能用于比较基本数据类型,如果没有对equals进行重写,则相当于“==”,比较的是引用数据类型变量所指地址值。

  • 注意:我们自定义的对象需要重写equals方法,一般情况下,类会重写equals方法用来比较两对象内容是否相等。如:String类中的equals()是被重写了,比较的是对象的内容。
    在这里插入图片描述

1.4 Integter缓存数组

1.4.1 引入案例发现问题

问题:我们发现,首先Integter是引用数据类型,但是,我们在做这两次比较判断的时候,却得到了两次不一样结果,如果说第二个FALSE得出是正常的,那第一个TRUE出现究极奇怪。
在这里插入图片描述

1.4.2 解释缓存数组

  • ① Integter有一个缓冲数组,将-128~127的所有数值,创建成Integter对象,提前放入到数组中。
  • ② i=100和i2=100,都是从数组中获取Integter对象,因为获取的是同一个,所以最终结果返回TRUE。
  • ③i3=300和i4=300,因为数组中不存在,则需new Integter()创建两次对象,两次对象的地址值不同,所以结果返回FALSE。

1.5 字符串常量池

注意:“==”号,在引用数据类型中,比较的都是地址值

1.5.1 案例一

        final String str2 = "ab";//在字符串常量池中创建“ab”,并将地址值赋值给str2
        System.out.println(str2);
        final String str3 = "cd";//在字符串常量池中创建“cd”,并将地址值赋值给str3
        System.out.println(str3);
        String str6 = new String("abcd");//在堆中开辟地址空间,并把得到的地址值赋值给str6
        String str4 = str2+str3;//在字符串常量池中得到abcd的地址
        System.out.println(str4);

        String str5 = "abcd";//在字符串常量池中创建abcd时,发现已有,不用创建,就使用创建好的地址值
        System.out.println("str4 = str5 : " + (str4==str5));//true

        System.out.println("str6 = str5 : " + (str6==str5));//false
        System.out.println(str6.equals(str4)); //true :String底层重写了equals比较的是对象的内容

1.5.2 案例二

String s1 = new String("abc");//堆中开辟新空间,得到新地址值
String s2 = new String("abc");//堆中开辟新空间,得到新地址值
System.out.println(s1 == s2);//false
System.out.println(s1.equals(s2)); // true:底层重写了equals方法

1.5.3 案例三

String s1 = "abc";//字符串常量池中创建abc,得到地址值
String s2 = new String("abc");//堆中开辟新空间,得到新地址值
s2.intern();//可以拿到s2的常量
System.out.println(s1 ==s2);//false

1.5.4 案例4

String str1 = "ab" + "cd";//先做计算得到abcd,字符串常量池中创建,并得到地址值
String str11 = "abcd";//字符串常量池发现已有,直接得到地址值
System.out.println("str1 = str11 : "+ (str1 == str11)); //TRUE

1.5.5 案例5

String str2 = "ab";//字符串常量池中创建,并得到地址值
String str3 = "cd";//字符串常量池中创建,并得到地址值
String str4 = str2+str3;//此处相当于str2+new String(str3)
String str5 = "abcd";//字符串常量池发现已有,直接得到地址值
System.out.println("str4 = str5 : " + (str4==str5));//false

1.5.6 案例6

final String str2 = "ab";//被final修饰的变量只能被赋值一次
final String str3 = "cd";//被final修饰的变量只能被赋值一次
String str4 = str2+str3;//“ab”+"cd"="abcd",并在字符串常量池中创建abcd,得到地址值
String str5 = "abcd";//字符串常量池发现已有,直接得到地址值
System.out.println("str4 = str5 : " + (str4==str5));//TRUE

1.5.7 案例7

String str6 = "b";//字符串常量池中创建b,得到其地址值
String str7 = "a" + str6;//此处相等于:“a”+new String(str6)
String str67 = "ab";//字符串常量池中创建ab,得到其地址
System.out.println("str7 = str67 : "+ (str7 == str67));//false

1.5.8 案例8

final String str8 = "b";//final修饰的变量,只能被赋值一次
String str9 = "a" + str8;//此处相等于:“a”+“b”先做计算得到值:ab,并在字符串常量池中创建ab,得到其地址值
String str89 = "ab";//在字符串常量池中,创建ab是发现已有,得到其地址值
System.out.println("str9 = str89 : "+ (str9 == str89)); //TRUE

1.5.9 案例9

String s1="Hello";//字符串常量池中创建并得到地址值
String s2="hello";//字符串常量池中创建并得到地址值
String s3=s1.toLowerCase();//将大写转为小写,但是地址值仍是先前的
String s4=s2.toLowerCase();//将大写转为小写,但是地址值仍是先前的
System.out.println(s3==s4);//false,==号在引用数据类型是比较的是地址值

2 两个对象的hashcode值相同,则equals是否也相同?

2.1 不对,两者间没有太大的关系

2.2 重写的hashCode方法调用

调用时以下算法
在这里插入图片描述

2.3 Arrays的hashCode方法

element.hashCode方法是native(用C语言写的)方法,无法再查看源码,不过能确定的是用个了啥算法。
因此,极端情况下,会发生哈希碰撞,即出现地址值相同结果
在这里插入图片描述

3 重写equals的时候需不需要重写hashcode呢?

需要重写

  • ① 当重写了equals和hashcode时,比如给HashMap存入数据时,先计算key的hash值,然后对数组长度取余,得到key在数组照片那个存储的位置,其次使用equals比对要存入的位置是否已有相同的数据,若相同,则替换,若不同,存入数组下面的链表中。
  • ②若自定义类中,没有重写hashcode方法,会调用其父类Object中的hashcode方法,默认是根据地址进行哈希运算,结果:两个值相同的对象实例,其hashcode值不一样,存入相同值在Map中
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值