ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

equals与==运用和区别(深入源码理解)

2021-11-23 21:59:53  阅读:159  来源: 互联网

标签:System String equals hashCode 源码 深入 println Integer


equals与==运用和区别(深入源码理解)

文章目录

双等号(==)

双等号比较的两种情况

对于==号只需要考虑两种情况:

  1. 基本数据类型使用==,比较的是值
  2. 引用数据类型使用==,比较的是变量(栈)内存中存放的对象的(堆)内存地址,用来判断两个对象的地址是否相同,即是否是指相同一个对象。比较的是真正意义上的指针操作。

源码和例子解析

Integer和Integer,Integer和int之间的比较

    Integer a1=new Integer(4321);
    Integer a2=new Integer(4321);
    int a3=4321;
    System.out.println("a1==a2:"+(a1==a2));//结果为false,因为a1,a2是两个不同的对象,其堆中的地址值自然不同
    System.out.println("a1==a3:"+(a1==a3));//结果为true,因为Java的自动拆箱机制,比较的是两个数值
    System.out.println("a3==a1:"+(a3==a1));//结果为false,原因同上
    Integer a4=4321;
    Integer a5=4321;
    /**
     * Integer a4=4321;
     * Integer a5=4321;
     * 相当于执行了
     * Integer a4=Integer.valueOf (4321) ;
     * Integer a5=Integer.valueOf (4321) ;
     */
    System.out.println("a4==a5:"+(a5==a4));//结果为false,相当于创建了两个对象,其地址自然不同
    
    Integer a6=100;
    Integer a7=100;
    /**
     * 为什么这个又不一样呢
     * 要根据装箱操作的源码
     * public static Integer valueOf(int i) {
     *         if (i >= -128 && i <= 127)
     *             return IntegerCache.cache[i + 127];
     *             //如果i的值大于-128小于127则返回一个缓冲区中已存在的一个Integer对象
     *         return new Integer(i);
     *         //否则返回 new 一个Integer 对象
     * }
     * 可以看出如果是-128-127之间,装箱装的是同一个对象(为了节约内存)
     *所以如果是-128到127之间的装箱操作,装的都是同样的对象!
     */
    System.out.println("a6==a7:"+(a6==a7));//为true
    Integer a8=128;
    Integer a9=128;
    System.out.println("a8==a9:"+(a8==a9));//为false
    Integer a10=-128;
    Integer a11=-128;
    System.out.println("a10==a11:"+(a10==a11));//为true
    a10=127;
    a11=127;
    System.out.println("a10==a11:"+(a10==a11));//为true
    /**
     * 注意,这种是直接生成对象的!
     * 没有进行装箱操作得到地址值,而是直接在堆创建生成的地址!
     * 所有不同的
     */
    Integer aa1=new Integer(1);
    Integer aa2=new Integer(1);
    System.out.println("aa1==aa2:"+(aa1==aa2));//为false

Java自动装箱拆箱机制的类型

image.png

String中==的解析

    String s1="12345";
    String s2="12345";
    String s3=new String("12345");
    String s4=new String("12345");
    /**
     * String s1=="xxx"这种字符串创建方式,并不是在堆中创建
     * 为了节省空间,是在运行时常量池,也就是在方法区中创建
     * s1和s2指向的是同一个地址
     */
    System.out.println("s1==s2:"+(s1==s2));//true
    System.out.println("s1==s3:"+(s1==s3));//false,s1指向的是常量池的地址,s3指向的堆中的地址
    System.out.println("s3==s4:"+(s3==s4));//false,s3和s4指向的是堆中不同的地址,所以false

equals

用法概述

equals没有被重写就是比较地址,相当于===

原因:
equals用来比较的是两个对象的内容是否相等,由于所有的类都是继承自java.lang.Object类的,所以适用于所有对象,如果没有对该方法进行覆盖的话,调用的仍然是Object类中的方法,而Object中的equals方法返回的却是==的判断。

equals源码
显然java源码对String类进行了特殊处理,String的equals以及不是比较地址值了,而是比较字符串的内容了。

image.png

image.png

  1. 首先两个对象在堆里面,地址值就不可能相等,所以要比较两个对象内容而不是地址时,必然要重写equals方法,比较内容
  2. hashCode默认情况下表示是对象的存储地址,如果两个东西相同,那么作为HashMap的key时应该是一样的,所以既然相等的规则变化了,自然要重写hashcode方法,跟随变化!

HashSet的equals

HashSet本身就重写了equals!

image.png

    HashSet<Integer> set1=new HashSet();
    HashSet<Integer> set2=new HashSet();
    set1.add(1);
    set1.add(2);
    set2.add(1);
    set2.add(2);
    System.out.println(set1.equals(set2));//返回true!

而且比较有意义的是
HashSet底层实现是通过HashMap实现的
image.png

数组的equals

Array的equals用的是原生的

image.png

image.png

    Integer[] array1={1,2,3};
    Integer[] array2={1,2,3};
    System.out.println(array1.equals(array2));//false
    
    //java.util.Arrays为我们提供了hashCode和euqals
    System.out.println(Arrays.equals(array1,array2));//true

但是java.util.Arrays为我们提供了hashCode和euqals,比较的是数组中的内部元素。

image.png

image.png
ps启发:
我们也可以学习这种方式
可以在不重写的方法下写一个通用类其中的方法进行计算hashcode和equals!

JAVA中重写equals()方法为什么要重写hashcode()方法

为什么重载hashCode方法?
答案:一般的地方不需要重载hashCode,只有当类需要放在HashTable、HashMap、HashSet等等hash结构的集合时才会 重载hashCode,那么为什么要重载hashCode呢?就HashMap来说,好比HashMap就是一个大内存块,里面有很多小内存块,小内存块 里面是一系列的对象,可以利用hashCode来查找小内存块hashCode%size(小内存块数量),所以当equal相等时,hashCode必 须相等,而且如果是object对象,必须重载hashCode和equal方法。

例如我们有对象A和对象B,现在重写了equals方法,让两者相等了,那我们用散列表HashSet存储了对象A,然后用set.contains(B),是查不到B存在的!

对象重写equlas和hashcode实例

package com.company;

public class Main {
    public static void main(String[] args) {
	// write your code here
        Person p1=new Person("l1",11,"男");
        Person p2=new Person("l1",11,"男");
        Person p3=new Person("l1",12,"男");
        System.out.println(p1==p2);//false
        System.out.println(p1.equals(p2));//true
        System.out.println(p1.equals(p3));//false
    }
}


class Person{
    String name;
    Integer age;
    String sex;
    @Override
    public int hashCode() {
        return 31*(this.name.hashCode()+31*this.age.hashCode()+31*(this.sex.hashCode()));
    }

    @Override
    public String toString() {
        return this.name+"  "+this.age+"  "+this.sex;
    }

    @Override
    public boolean equals(Object obj) {
        Person person1=(Person) obj;
        return this.hashCode()==person1.hashCode();
    }

    public Person() {
    }

    public Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
}

outPut

false
true
false
Process finished with exit code 0

Ps: 如果要用equal方法,请用object<不可能为空>.equal(object<可能为空>))
"target".equals(foo)

标签:System,String,equals,hashCode,源码,深入,println,Integer
来源: https://blog.csdn.net/weixin_44153921/article/details/121503833

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有