Java ==,equals,hashCode,解析(适合初学者阅读)

1.对于equals()和hashCade()方法他们都是位于Java.lang.object类下的方法,又因为所有的类都继承于objct类,所以所有的类都可以使用这两个方法.

2.对于equals()方法,首先知道他是用于比较的,这里我吧源码打出来(注意:我这打出的源码是Object类中的equals()方法的源码)

  public boolean equals(Object obj){

  return (this==obj);

  }

附录:this关键字我在这里进行简单的说明一下吧,对于初学者对this这个关键字有好多人都不是很理解. 这里的this是指当前对象自己.

  我写一段代码: public classs ChenShun{

  public String name;

  public String setName (String name){

  this.name=name;

  System.out.println(this);//这里我打印this

}(注意:这段代码我中的name变量我用颜色区分一下表示,相同的颜色表示他们代表着同一个变量)

  public class A{

    ........

  ChenShun chenshun=new ChenShun();

  chenshun.setName("威猛叔叔");//这里我掉用了 ChenShun类中的setName方法

  System.out.println(chenshun);//这里我打印chenshun这个对象

    .......

}

结果是两处打印的值是相同的,从这里我们可以得出一个信息这里的this指代的就是chenshun这个对象,好了this就先讲到这里

我们接着看一下这个源代码 return(this==obj);我想对于 "==""这个符号大家都是不太陌生的吧,什么!你没见过这个符号! 0_0

好吧我就稍微的说一下"=="这个符号吧

附录:"==" 表示比较的是2个对象的地址 我想大家应该是知道的 数据的类型是分为两个大类的,值类型,和引用类型,如果这不清楚,我觉得你的基础简直不要不要的

但是为了大家我还是要说明一下的,看代码

借用上面定义的类

ChenShun chenshun =new ChenShun();

别小看这一句话,有很多面试的考官会问你,这句话做了什么,如果你不理解,那就呵呵了!

首先我这里要说两个东西,堆(Heap)和栈(Stack),你可以先理解为他们是分别的两个存储空间.

好了我们接着看代码

ChenShun chenshun; //这叫做声明,我声明了一个叫chenshun的Chenshun类型变量.

new ChenShun();//这叫做创建,我创建了一个ChenShun的对象.

chenshun=new ChenShun();//将对象"赋值"给chenshun这个变量,其实这样说,我个人认为说的也不是很准确.主要在于"赋值"这个"值"字上,这个值是什么呢?

再回头看一下这个代码,ChenShun chenshun=new ChenShun();

我用着样一句话说明一下,创建一个"引用" (ChenShun chenshun),创建一个"对象"(new ChenShun();),JAVA模型中有堆和栈两个内存空间,将引用放入栈中,将对象放入堆中"引用的值就是对象在堆中的地址","对象的值就是实际数据",这就是引用类型.

Java的8种特殊类型数据: byte,short,int,long,char,boolean,float,double .这几种类型不是对象其值直接放入栈中  看代码 int i=1 ; i放入栈中 值是1,而值不是对象的地址,这就是值类型.

好了这里就可以回归到"==""符号比较的是两个对象的地址.

那么这样看代码:

ChenShun chenshun=new ChenShun();

ChenShun chenshun1=new ChenShun();

ChenShen chenshun2=chenshun;

System.out.println(chenshun==chenshun1);//false

System.out.println(chenshun2==chenshun);//true

这样,我想你们就应该知道 他比较的是什么东西了吧!

如果仔细的看我写的东西,当然限于初学者,看到了8种基本类型中没有String类型,我想你们应该可以猜到了String是不属于基础类型的,我之前有说过,

JAVA的数据类型只有两种,分别是值类型,和引用类型,没错String是属于引用类型的,这里有点扯远了,但是我觉得还是有必要将String说一下,因为

有很多的面试官喜欢问这个问题.

String 是字符串,这我想大家都是知道的,那什么是字符串呢,要是让你写一个字符串,你可以马上抬手打出来.

看代码:

String x="abc";

是吧很简单的,但是你深入的了解过吗?我想许多的初学者都没有了解过,但是面试官问起来,你就是不知怎么去回答.

好吧,你可以这样去理解字符串,所闻的字符串,就是许多的字符连接起来,你肯点想,我靠这是什么回答,我只想说,这就是字符串的定义

让我们看看,字符串是许多的字符连接起来就是字符串,这就是答案.

不服我们看看源代码:

Java.lang.String

public final class String implements java.io.Serializable, Comparable<String>, CharSequence{ //注意这行代码我标红的位置,我想你们应该知道这个关键字的用途.

.........  

  public String(){

    this.value = new char[0]; //看到没,new char[0],创建了一个空的字符数组,你不服我不辩,这里就证明了我上面说的,所谓的字符串就是许多的字符串在一起

  }

........

}

关于更多的String这方面的东西我就不再这了深入的表述了,让我们回到正题上,我有时间的话会写一篇关于String的详解出来

有的人会问,你说比较方面的东西怎么会扯到String上面去,我只想这样回答,String是特殊的比较对象,我们要特殊的回答.

看代码:

String x="abc";

String y="abc";

String k=new String("abc");

String h=new String("abc");

String m=k;

System.out.println(x==y);//这个结果是什么?

System.out.println(x==k);//这个结果是什么?

System.out.println(k==h);//这个结果是什么?

System.out.println(m==k);//这个结果是什么?

仔细想想

答案是:true,false,false,,true

有的人,心想,我靠这TMD不科学 为什么 x==y的值是true,你不是说,String是引用类型吗? 那String x="abc"; 和 String y="abc" 不是创建了两个对象吗?

我想这样告诉你们,哈哈你们太天真了,这里有一个面试官常会问的问题,String 是不是可变的类型,答:"不是!",String是不可变类型的

String类型的本质是char[]

还记得上面String类源代码我写的什么吗?

public String(){

  this.value=new char[0];

}

对了这里的value属性,在String类中, value属性是这样定义的:private final char value[]; ╮(╯▽╰)╭不要怪我套路深,这是没有办法的,不这样坑你们一下,你们很难记住.

那好,问题来了,既然是不可变的话,我们有时候又喜欢用到字符串就随意定义一个,这样会对内存造成很大的消耗,那怎么办?有时候就重复的定义了相同的字符串!

好吧Java帮我们想出了一个办法,只要你的程序在运行的时候,我就给你开辟一个区域(StringPool)也叫作String池.

String池用来存放运行时产生的各种字符串,并且池中的字符串不存在重复.OK这就是原因了,有重复的字符串他就直接将引用了池中的字符串了,所以

System.out.println(x==y); 结果为true 因为当创建 String x="abc";的时候就将 字符串放入到了 String池中,当你 String y="abc";的时候,Java会到

String池中找是否有字符串"abc",如果存在"abc"就将该字符串的内存地址直接给y,好了这就是为什么 x==y.

那有的人又要问了,那为什么x==k的结果是false,那是因为 new 这个关键字造成的,你们可以这样记住,在Java中只要使用new关键字创建对象,那么一定会在(堆区或栈区)创建一个新的对象,换句话,new关键字创建的对象在堆或是栈中,String x="abc";这样写的代码生成的是在String池中,位置都不一样,这样肯定结果就是false.

这样大致上的"=="比较符算是讲的差不多了,有些知识需要自己去百度,百度才是你最好的老师!

又回到之前所讲的东西了equals(),(终于讲回来了),为了避免你往上翻,那么我就在打一遍 object类中的equals()的源码

看代码:

public boolean equals(Object obj){

  return (this==obj);

}

咦?你肯定会奇怪了 这里用的是== 符号,怎么和我实际用到有点不一样啊,既然是==符号,那我还用什么equals(),直接==就可以了.

如果你这么想,好吧,我之呵呵不说话

看代码:

  String str= new String("abc");

  String str1=new String("abc");

  System.out.println(str.equals(str1));//结果是什么呢? 仔细想想

答案是: true

WTF,这和之前的分析是不同的.

这里又有一个要讲,那就是String重写了equals()方法.

看代码:

Java.lang.String

  public final class String  implements java.io.Serializable, Comparable<String>, CharSequence{

  ........

  public booleam equals( Object anobject){

    if(this==anobject){

      return true;

    }

    if(anobject instanceof String){ //这里的 instanceof 关键字用于判断一个引用类型变量所指向的对象是否是一个类(或接口、抽象类、父类)的实例

      String anotherString=(String)anobject;

      int n=value.length;

      if(n==anotherString.value.length){      

        char v1[] = value;
        char v2[] = anotherString.value;
        int i = 0;
        while (n-- != 0) {
          if (v1[i] != v2[i])
          return false;
          i++;
        }
        return true;

      }

    }

     return false;

  }

  ........

  }

  

可以看出这是重写了equals(),这里就是比较了两个 字符串是否是一样的,好了,但是有一点要记住只要重写了 equals() 有必要重写hashCode();

接下来我们来看一下

Object类中的 hashCode()方法,我会在后面说名 hashCode()

看代码:

Java.lang.Object

  public native int hashCode();//在Object类中就是这样的一行代码,注意我这里标红的 关键字native,好吧对于初学者,这个关键字实在是用的太少了,基本上是不用这个关键字,但是我还是在这里稍微的说明一下这个关键字的用途.

要知道Java是不完美的语言,Java是无法直接访问操作系统的底层的,怎么办,对了C语言可以啊,那好吧,那我就叫C语言帮我在底层做一些操作,但是我怎么让C语言和我Java进行沟通呢,这时候我们就用到了native关键字,这就像是Java和C之间的一个接口,实际上java就是在不同的平台上调用不同的native方法实现对操作系统的访问的,这其实就涉及到了Java的底层,初学者现在不必过余的去深究,这里你就看成我在这里调用了一个C写好的hashCode()方法.

好的,让我来了解一下hashCode();

我们来先看看权威的说明(官方的说明)

  1. hashcode方法返回该对象的哈希码值。支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表。
  2. hashCode 的常规协定是:
  3. 在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
  4. 如果根据 equals(Object) 方法,两个对象是相等的,那么在两个对象中的每个对象上调用 hashCode 方法都必须生成相同的整数结果。
  5. 以下情况不 是必需的:如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么在两个对象中的任一对象上调用 hashCode 方法必定会生成不同的整数结果。但是,程序员应该知道,为不相等的对象生成不同整数结果可以提高哈希表的性能。
  6. 实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
  7. 当equals方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。

对于初学者来说有点太官方了是吧,那就看看下面的总结(别人写的,我Ctrl+C过来的,这是我之前看的微博,觉得总结的很漂亮)

1.hashCode主要是用来快速的查找,你可以理解为是一个索引,比如查找HashTable,HashMap,HashCode主要是用来在散列存储结构中确定对象的存储地址的.

2.如果两个对象相同,就是适用于equals(Java.lang.Object) 方法,那么这两个对象的hashCode一定要相同

3.如果对象的equals方法被重写,那么对象的hashCode也尽量重写,并且产生hashCode使用的对象,一定要和equals方法中使用的一致,否则就会违反上面提到的第2点

4.两个对象的hashCode相同,并不一定表示两个对象就相同,也就是不一定适用于equals(java.lang.Object) 方法,只能够说明这两个对象在散列存储结构中,如Hashtable,他们“存放在同一个篮子里”

好了这就是总结,我无耻的笑了一下.

再归纳一下就是hashCode是用于查找使用的,而equals是用于比较两个对象的是否相等的。以下这段话是从别人帖子回复拷贝过来的:

1.hashcode是用来查找的,如果你学过数据结构就应该知道,在查找和排序这一章有
例如内存中有这样的位置
0  1  2  3  4  5  6  7
而我有个类,这个类有个字段叫ID,我要把这个类存放在以上8个位置之一,如果不用hashcode而任意存放,那么当查找时就需要到这八个位置里挨个去找,或者用二分法一类的算法。
但如果用hashcode那就会使效率提高很多。
我们这个类中有个字段叫ID,那么我们就定义我们的hashcode为ID%8,然后把我们的类存放在取得得余数那个位置。比如我们的ID为9,9除8的余数为1,那么我们就把该类存在1这个位置,如果ID是13,求得的余数是5,那么我们就把该类放在5这个位置。这样,以后在查找该类时就可以通过ID除 8求余数直接找到存放的位置了。  

2.但是如果两个类有相同的hashcode怎么办那(我们假设上面的类的ID不是唯一的),例如9除以8和17除以8的余数都是1,那么这是不是合法的,回答是:可以这样。那么如何判断呢?在这个时候就需要定义 equals了。
也就是说,我们先通过 hashcode来判断两个类是否存放某个桶里,但这个桶里可能有很多类,那么我们就需要再通过 equals 来在这个桶里找到我们要的类。
那么。重写了equals(),为什么还要重写hashCode()呢?
想想,你要在一个桶里找东西,你必须先要找到这个桶啊,你不通过重写hashcode()来找到桶,光重写equals()有什么用啊

在这里我贴出Java.lang.String类的hashCode源码

  public int hashCode() {
        int h = hash;
        if (h == 0 && value.length > 0) {
            char val[] = value;

            for (int i = 0; i < value.length; i++) {
                h = 31 * h + val[i];
            }
            hash = h;
        }
        return h;
    }

  

最后我总结一下吧

1.对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;

    如果作用于引用类型的变量,则比较的是所指向的对象的地址

2.对于equals方法,注意:equals方法不能作用于基本数据类型的变量

    如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;

    诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。

3.hashCode是用来查找用的,如果重写了equals,那么请把hashCode也重写一下,不然放入hashSet中会出现问题的,具体什么问题希望你们自己尝试一下.

 

好了,博文就写到这里了,妈呀,累死我了,如果我有什么没写对的请一定要指出来,感激不尽~~~~~~?(^?^*)

时间: 2024-08-15 11:59:32

Java ==,equals,hashCode,解析(适合初学者阅读)的相关文章

关于JAVA面向对象基础整理以及个人的理解(适合初学者阅读)

JAVA的基础语法等都跟C有很大的相似之处,所以这里就不多啰嗦了.直接从数组开始. 数组: 1.声明 int [] a; 在声明的过程中,并没有分配空间给数组.我们可以在声明的同时,用new来分配相应的空间 int [] a = new int[100]; 这里开辟了一个空间为100大小的数组,内存分配也完成了. 我们可以在声明的同时也确定元素个数 int [] a = new int[]{1,3,5,7,9}; 面向对象(重点) class Human{ int height; void br

面试点:Java 中 hashCode() 和 equals() 的关系

Java 中 hashCode() 和 equals() 的关系是面试中的常考点,如果没有深入思考过两者设计的初衷,这个问题将很难回答.除了应付面试,理解二者的关系更有助于我们写出高质量且准确的代码. 一.基础:hashCode() 和 equals() 简介 在学习 hashCode() 和 equals() 之间的关系之前, 我们有必要先单独地了解他俩的特点. equals() equals() 方法用于比较两个对象是否相等,它与 == 相等比较符有着本质的不同. 在万物皆对象的 Java

java Socket多线程聊天程序(适合初学者)

一个非常简单的java聊天程序,有客户端和服务器端,目前只有群聊功能,其他的所有功能都可以在这个基础上添加,现在我分享出来主要是为了保持一个最简单的java聊天程序便于初学者学习,界面也非常的简洁,只有两个文件,主要是用了socket,java多线程,知识点不是很多,很适合初学者 下面是服务器端代码 package tk.socket; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.event.Act

推荐几本适合初学者的Java书籍

学习java哪本书比较好?作为Java初学者,我想这是问的最多的问题了老,下面整理一些学习java的好书推荐给大家,希望对大家学习java有所帮助. Java入门好书推荐:<Head First Java> <Head First Java>是本完整的面向对象(object-oriented,OO)程序设计和Java的学习指导.此书是根据学习理论所设计的,让你可以从学习程序语言的基础开始一直到包括线程.网络与分布式程序等项目.最重要的,你会学会如何像个面向对象开发者一样去思考.但如

Java 中 hashCode 和 equals 方法 小结

转载:http://www.oschina.net/question/82993_75533 hashCode()和equals()定义在Object类中,这个类是所有java类的基类,所以所有的java类都继承这两个方法. hashcode主要是set集合使用,是用于判断对象是否”可能“相等的快捷办法,以解决大集合的问题.举例来说,如果一个一万个元素的集合加入一个元素,如果是一个新元素,那么必须要equal一万次才能加入.所以采用hashcode,hashcode的思路是如果equal,则ha

java 中hashcode和equals 总结

一.概述            在Java中hashCode的实现总是伴随着equals,他们是紧密配合的,你要是自己设计了其中一个,就要设计另外一个.当然在多数情况下,这两个方法是不用我们考虑的,直接使用默认方法就可以帮助我们解决很多问题.但是在有些情况,我们必须要自己动手来实现它,才能确保程序更好的运作. 1.1 规则 粗略总结一下在JavaDoc中所规定hashcode方法的合约:      Objects that are equal must have the same hash co

java 笔记 == , equals , hashcode()的区别

== , equals , hashcode()的区别: 基本数据类型:比较用==, 比较他们的值 复合数据类型:用==比较时,比较的是它们在内存中存放的地址,除非是同一个new出来的对象,他们的比较后果为true,否则为false. object基类中定义了equals()方法,它的初始行为是比较它们的内存地址(就是和==功能一样),但在有些类库中覆盖了,比如String类的equals()方法是比较它们的内容.equals()方法在object类中定义如下:   public boolean

实验楼一个很好的IT学习平台,包括JAVA,LINUX,HTML,C,CSS,JS等适合初学者

实验楼一个很好的IT学习平台,包括JAVA,LINUX,HTML,C,CSS,JS等适合初学者,网址 网址链接点击打开

《软件工程思想-适合初学者》阅读笔记3

今天读完<软件工程思想-适合初学者>最后两章和作者大学十年的经历,第7章是测试与改错, 再次回顾了老师上课所讲测试的目的,发现更多的缺陷然后改正.还有学习到了一些测试方法,比如 正确性测试.容错性测试.性能与效率测试.易用性测试.文档测试.第八章是维护与再生工程,对 于维护我可能了解一些,主要是纠错性维护.适应性维护和完善性维护等等,也学习到一些维护的所 付出代价与影响维护代价的因素.对于再生工程刚开始看到这一名词有些陌生,后来看到重构.逆向 工程.前向工程我就有了一些熟悉感,老师上课提到了重