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