博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
从equals和==的区别开始
阅读量:4357 次
发布时间:2019-06-07

本文共 6555 字,大约阅读时间需要 21 分钟。

 

        今天我要谈的,不是具体的一个小程序的设计,也不是什么高大上的遗传算法群体智能什么什么的理念。今天我想就非常简单的一个问题,深入地解释一些东西,把自己的一些看法传达给大家。我相信,认真看下去,大家会有所收获。闲话不多谈,我们进入我们今天的正题。

        我相信很多Java的初学者都会碰到这样一个问题,那就是equals和==究竟有什么不同。小编百度了一下,在我看来,大多数网上的答案虽然讲清楚了他俩之间的区别,但是,并没有理清楚两者的本质区别。至少从Java的角度来说,并不完全正确。

        我们先来看一下下面的这一段程序:

1 public class bool { 2     public static void main(String[] args) { 3         String a = "a"; 4         String b = "b"; 5         String c = "ab"; 6         String d = a+b; 7         System.out.println(c.equals(d)); 8         System.out.println(c==d); 9     }10 }

       我相信,两者的输出大家都能猜到,前者输出的是true,而后者输出的是false。

        接下来,我们将具体深入到Java的源码里,去寻找我们要的答案。

        首先,我们通过F3找到println方法,对于参数类型为boolean值的参数,调用的是如下的方法:

        对于synchronized我们先不去谈,这是Java中的一个关键字,表示一种同步锁。我们看到该方法调用了两个方法,一个是print,一个是换行。我们继续按F3去查询print(x)的源码:

        走到这一步我们发现,在print(boolean b)方法里面用到了三目运算符,如果b为真,在控制台输出“true”(注意一下,这里输出的是字符串!!!),如果b为假,则在控制台输出“false”。这也就解释了,为什么我们打印的明明是一个boolean值,输出的确实true和false的字符串了。

        那么,解决了这个问题,我们回到最开始的问题,c == d和c.equals(d)究竟有什么区别?

        事实上,通过查看源码,我们能够很清楚地辨别出两者的不同。

 

/**     * Compares this string to the specified object.  The result is {
@code * true} if and only if the argument is not {
@code null} and is a {
@code * String} object that represents the same sequence of characters as this * object. * * @param anObject * The object to compare this {
@code String} against * * @return {
@code true} if the given object represents a {
@code String} * equivalent to this string, {
@code false} otherwise * * @see #compareTo(String) * @see #equalsIgnoreCase(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; }

        我们可以很清楚地看到,在String类的equals方法里,在if(this == anObject)的基础上,还加了一层判断,那就是如果anObject是字符串的话,它将会比较一下两个字符串是否相同,若相同,返回true。也正是因为在方法里,多加了这么一层判断,c == d和c.equals(d)的结果会完全不同。

        事实上,看到这里,我相信,我已经向大家讲述明了==和equals的区别,那就是equals会多加上一层若是两者类型相同时的比较。但是,既然走到了这一步,我们不妨继续往下走一走。我们都知道,Java里面所有类继承自Object。事实上,String类里面的equals方法是重写来自Object里面的equals方法。通过查阅,我们查到了Object里的源码:

/**     * Indicates whether some other object is "equal to" this one.     * 

* The {

@code equals} method implements an equivalence relation * on non-null object references: *

    *
  • It is reflexive: for any non-null reference value * {
    @code x}, {
    @code x.equals(x)} should return * {
    @code true}. *
  • It is symmetric: for any non-null reference values * {
    @code x} and {
    @code y}, {
    @code x.equals(y)} * should return {
    @code true} if and only if * {
    @code y.equals(x)} returns {
    @code true}. *
  • It is transitive: for any non-null reference values * {
    @code x}, {
    @code y}, and {
    @code z}, if * {
    @code x.equals(y)} returns {
    @code true} and * {
    @code y.equals(z)} returns {
    @code true}, then * {
    @code x.equals(z)} should return {
    @code true}. *
  • It is consistent: for any non-null reference values * {
    @code x} and {
    @code y}, multiple invocations of * {
    @code x.equals(y)} consistently return {
    @code true} * or consistently return {
    @code false}, provided no * information used in {
    @code equals} comparisons on the * objects is modified. *
  • For any non-null reference value {
    @code x}, * {
    @code x.equals(null)} should return {
    @code false}. *
*

* The {

@code equals} method for class {
@code Object} implements * the most discriminating possible equivalence relation on objects; * that is, for any non-null reference values {
@code x} and * {
@code y}, this method returns {
@code true} if and only * if {
@code x} and {
@code y} refer to the same object * ({
@code x == y} has the value {
@code true}). *

* Note that it is generally necessary to override the {

@code hashCode} * method whenever this method is overridden, so as to maintain the * general contract for the {
@code hashCode} method, which states * that equal objects must have equal hash codes. * * @param obj the reference object with which to compare. * @return {
@code true} if this object is the same as the obj * argument; {
@code false} otherwise. * @see #hashCode() * @see java.util.HashMap */ public boolean equals(Object obj) { return (this == obj); }

        我们可以看到,对于所有类的基类Object来说,它的equals判断就是==。然而,我们比较的往往是一些基本的数据类型,而在这些基本类型的封装类里面的equals方法一般是重写过的。比如String类里加入了对于比较对象为String类的特别处理。

        在这里,我刻意避开了一个问题,那就是为什么c == d是错的输出。如果是之前的我,我一定会立马说,String是一个类,而不是普通的基本数据类型,类创建的对象的内容相等不代表就是一个对象。但是,之后学到更多的内容之后,我发现我想的还是比较简单了。谈一点大家就知道为什么了,既然String是一个类,为什么它的实例除了通过new关键字外,还能跟基础数据类型一样直接赋值呢?所以说,String其实是一个比较特殊的类,它的特别使得这种判断变得更为复杂。

        在这里稍微讲解一些String的特殊机制。我们都知道字符串类型的数据有这么两种常见的定义方式。1、String str = "abc";2、String str = new String("abc");。这里就设计到了String类型的内存分配问题了。简单来说,对于前者,“abc”会放入一个叫做常量池的东西里面,之后如果再有类似的定义方式,它会首先查询常量池中是否存在“abc”,若存在,则直接指向同一个“abc”,若不存在,则在常量池中加入“abc”,并指向它。也就是说,在使用第一种定义方式的时候,无论你定义多少个对象,它们都是同一个。但是通过new创建的,是一个完完全全新的对象。这也就解释了,为什么 c == d是错误的输出了。大家理解了吗?为了方便大家更加深刻地理解,小编准备了如下的一段代码,大家可以进行比对一下,这样能有更加深刻的认识:

 

1 public class String_Text { 2     public static void main(String[] args) { 3         String str1 = "abc"; 4         String str2 = "abc"; 5         String str3 = new String("abc"); 6         String str4 = new String("abc"); 7         System.out.println(str1 == str2); // true 8         System.out.println(str1.equals(str2));// true 9         System.out.println(str1 == str3);// false10         System.out.println(str1.equals(str3));// true11         System.out.println(str3 == str4);// false12         System.out.println(str3.equals(str4));// true13     }14 }

 

        如果说,各位看客还有什么疑问的话,这里还有一片博客推荐哟,。这是小编一个学长大神大佬写的一篇博客,小编关于String内存分配部分的知识,也是从当中学到的。各位看官如果看完小编的文章觉得不满,觉得还比较浅显,或者还没看够的,可以去拜读一下这篇博客哟。强势推荐一波逸情公子大大!!更多的东西,小编也就不再赘述了,总之,学东西,不能浅尝辄止哟。那么,各位看官下次再见!

 

 

 

转载于:https://www.cnblogs.com/PHBlog/p/7294735.html

你可能感兴趣的文章
数据字典的转换
查看>>
二维数组按照指定的字段排序的函数
查看>>
在IAR下通过Jlink将程序直接下载到Flash指定地址
查看>>
POJ2560-雀斑(Freckles)【图论,并查集,最小生成树,KURUSKAL】
查看>>
[Angular] Tree shakable provider
查看>>
[Vue + TS] Use Dependency Injection in Vue Using @Inject and @Provide Decorators with TypeScript
查看>>
[Angular 2] Select From Multiple Nested Angular 2 Elements
查看>>
C# 中的委托和事件[转帖]
查看>>
图的遍历(bfs+dfs)模板
查看>>
angular service 进行组件通信
查看>>
linux安装Mac的默认Monaco字体
查看>>
java语言的特点
查看>>
关于动态添加iview admin路由以及刷新侧边栏
查看>>
ApplicationInsights的探测器尝鲜
查看>>
java 解析Json格式数据
查看>>
unix中的线程池技术详解
查看>>
CSS简介
查看>>
常用三大软件评价1
查看>>
MVC各层介绍使用---初步理解
查看>>
单例对象的创建与销毁
查看>>