Java中equals()方法分析

来源:互联网 发布:网络语浪是什么意思 编辑:程序博客网 时间:2024/05/28 15:48

Java中equals()方法分析

绝对是一道笔试题引发的‘血案’,前两天参见某公司的面试题,其中考到了关于Javaequals()方法的一道题。话不多说,先看一下这个题:

Integer i=100,j=100,s=128,k=128;System.out.print(i==j);System.out.print(i.equals(j));System.out.print(s==k);System.out.print(s.equals(k));

结果为:true true false true

原因:JVM使用缓存池来管理整型,并且范围在-128到127如果int直接超过这个返回,那么Integer会调用构造器创建一个新的Integer对象,例如题目中

s=128
k=128

其实质是相当于

Integer s=new Integer(128);

Integer K=new Integer(128);

上面题目代码可等价转换如下代码:

Integer i=new Integer(100);Integer j=i;Integer s=new Integer(128);Integer K=new Integer(128);System.out.print(i==j);System.out.print(i.equals(j));System.out.print(s==k);System.out.print(s.equals(k));

在java中引用类型,比较方式有两种equals()==

equals()==比较变量类型区别:

使用==比较的变量有两种类型:

1、比较变量均为基本数值类型,则只要两个变量的值相等,就返回true;

2、比较变量为引用类型变量,只有它们指向同一个对象时,才返回true;

PS:==用于比较引用类型时必须一致或者为父子关系的对象。

使用equals()比较的变量为引用类型变量。


所有的类都继承与object类,我们先看以下objectequals()方法

public boolean equals(Object obj) {         return (this == obj);         }  

可以了解到objectequals()方法是有==操作符来实现的。因此只要比较实例的类没有重写equals()方法,那么equals()方法与==比较的结果是一致的。都表示内存中存放地址的比较。

根据equals()方法是否被重写,将所有的引用类型分为:重写型(equals()方法被重写)、继承性

一、继承性(equals()方法没有被重写)

对于equals()方法没有被重写的引用类型,只要是被同一个new创建的实例,起比较的结果都为true,否则为false

此时== 与equals()等价

例如:

A a=new A();A b=new A();A c=a;System.out.println(a.equals(b));System.out.println(a==b);System.out.println(a.equals(c));System.out.println(a==c);

结果:false false true true

这表明new表示在JVM堆中创建一个新的空间来存放实例。所以ab变量指向不同的内存空间。ac指向同一空间。

一、重写型(equals()方法被重写)

这里介绍几个JDK中已经对equals()方法重写的类。

1、String

下来看一下String源码

public boolean equals(Object anObject) {          if (this == anObject) {              return true;          }          if (anObject instanceof String) {              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;      }  

源码分析:

if (this == anObject) :当两个String类型实例指向同一内存空间,答案是肯定的true

if  当两个实例并不指向同一内存空间时,分析源码可以知道,当这两个实例的字符串内容相同时,仍然返回true

总结:String equals()方法比较的实质是两个字符串内容是否相等,与内存地址无关

            String通过==比较的是内存地址(==比较内存地址是不会变的)

例如:

String a="one";String b="one";String c=new String("one");System.out.print(a.equals(b));System.out.print(a.equals(c));System.out.println(a==b);System.out.println(a==c);

于此类似的还有Integer、Date,它们都对equals()方法重写,比较的是指都是实例的内容而不是内存地址。

这里String的直接赋值也是JVM缓存池的作用在里面。因此a,b的内存地址一致。


回归到题目中,Integer的equals()也是比较的内容,因此只要内容值相等,equals()方法就返回true.
System.out.print(s.equals(k));
System.out.print(i.equals(j));
返回true;
按照道理将System.out.print(s==k);应该与System.out.print(i==j);一样都应该返回true.但是没有因为这里有点特殊,牵扯到了Java中常量池的内容。这里简要说一下,int常量池中初始化-128~127的范围,所以Integer i 当i的值在范围之内,取数值,而当i超出范围时,需new 一个新的实例,地址将发生变化。
因此System.out.print(s==k); 输出值为false

1 0
原创粉丝点击