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

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

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

 public class bool {
public static void main(String[] args) {
String a = "a";
String b = "b";
String c = "ab";
String d = a+b;
System.out.println(c.equals(d));
System.out.println(c==d);
}
}

我相信,两者的输出大家都能猜到,前者输出的是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.
* <p>
* The {@code equals} method implements an equivalence relation
* on non-null object references:
* <ul>
* <li>It is <i>reflexive</i>: for any non-null reference value
* {@code x}, {@code x.equals(x)} should return
* {@code true}.
* <li>It is <i>symmetric</i>: 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}.
* <li>It is <i>transitive</i>: 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}.
* <li>It is <i>consistent</i>: 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.
* <li>For any non-null reference value {@code x},
* {@code x.equals(null)} should return {@code false}.
* </ul>
* <p>
* 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}).
* <p>
* 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是错误的输出了。大家理解了吗?为了方便大家更加深刻地理解,小编准备了如下的一段代码,大家可以进行比对一下,这样能有更加深刻的认识:

 public class String_Text {
public static void main(String[] args) {
String str1 = "abc";
String str2 = "abc";
String str3 = new String("abc");
String str4 = new String("abc");
System.out.println(str1 == str2); // true
System.out.println(str1.equals(str2));// true
System.out.println(str1 == str3);// false
System.out.println(str1.equals(str3));// true
System.out.println(str3 == str4);// false
System.out.println(str3.equals(str4));// true
}
}

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

从equals和==的区别开始的更多相关文章

  1. java equals和==的区别

    大概说equals和==都比较的是什么: 1. boolean tem = a == b; 首先==比较的肯定是地址,从堆栈的角度说也就是说==比较的是栈上面的内容.因为栈是用来存放地址或是java中 ...

  2. equals与==的区别

    equals与==的区别. 下面是equals的源码 public boolean equals(Object anObject) { if (this == anObject) { //如果两个对象 ...

  3. equals和==的区别 你真的掌握了吗?

    PS:最近读Java编程思想的时候发现了一些小问题.就是equals方法和==,感觉自己是真正掌握了,其实并没有.简单的记录一下. 学习内容: 1.equals 和 == 的区别  equals和== ...

  4. 【ASP.net】Equals 和 == 的区别

    在比较Equals 和 ==的区别前.我们先来了解下相关的知识 C#数据类型 1.值类型 值类型有: 值类型包括:简单类型.结构类型.枚举类型:引用类型包括:Object 类型.类类型.接口.代表元. ...

  5. 【java】由equals和==的区别引出的常量池知识

    equals和==的区别,百度查到的结果大都是:equals比较的是值,==比较的是引用地址. String str1 = "abc"; String str2 = "a ...

  6. 比较compareTo与equals及==的区别

    1.compareTo: 附上:源码: public int compareTo(String anotherString) {         int len1 = value.length;   ...

  7. Java笔记——equals和==的区别

    摔在这里几次,还是记下来吧. 原文:http://www.cnblogs.com/shenliang123/archive/2012/04/16/2452156.html -------------- ...

  8. java中equals和==的区别 (转)

    java中equals和==的区别  值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中. ==操作比较的是两个变量的值是否相等,对于引 ...

  9. equals()和hashCode()区别?

    equals()和hashCode()区别? ------------------------------------------------- equals():反映的是对象或变量具体的值,即两个对 ...

  10. 【转】Java中equals和==的区别

    [转]Java中equals和==的区别 java中的数据类型,可分为两类: 1.基本数据类型,也称原始数据类型.byte,short,char,int,long,float,double,boole ...

随机推荐

  1. 【解决】VS2013 + Qt 5.7(5.6适用)使用QSqlDatabase出现“无法解析的外部符号"错误

    原始日期: 2016-08-03 22:09  错误如下: error LNK2019: 无法解析的外部符号 "__declspec(dllimport) public: __thiscal ...

  2. 批量自动更新SVN版本库 - Windows

    开发过程中每天都要从SVN代码库里一个一个的update各个项目代码,不仅效率实在是低,也不符合程序员的"懒"精神,由于是在Windows环境做开发,自然就想到了使用bat来实现自 ...

  3. js数值使用及数组转json,转化后的json传入后台解析

    var storeArray=new Array(); $("input[name='storeid']").each(function(i){ var curStoreObj = ...

  4. 记一次服务器Tomcat优化经历

    公司需要一台测试服务器来做测试用,所以花了几天时间把服务全部部署好,在部署好war包之后,发现Tomcat访问超级慢. 1.进入Tomcat的bin目录下,运行 ./catalina.sh run命令 ...

  5. 解决微信浏览器禁止链接跳转到iTunes

    方法:微信页面通过safari浏览器打开 safari打开的时候进行跳转 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transition ...

  6. leetcode-486-Predict the Winner

    Given an array of scores that are non-negative integers. Player 1 picks one of the numbers from eith ...

  7. WCF学习——构建第二个WCF应用程序(五)

    一.创建数据服务 1.在“解决方案资源管理器”中,使用鼠标左键选中“WcfService”项目,然后在菜单栏上,依次选择“项目”.“添加新项”. 2.在“添加新项”对话框中,选择“Web”节点,然后选 ...

  8. touchmover 手机端拖动方法

    function drag(obj, parentNode) { var obj = document.getElementById(obj); if (arguments.length == 1) ...

  9. MyEclipse 2014 破解补丁及激活步骤

    针对 MyEclipse Trail Expired 问题的解决方法 我用网上找的注册类生成注册码的方式注册了一下,重启MyEclipse仍然会有提示弹窗,不过剩余时间由 4 days变成了 5 da ...

  10. 论MyBatis日志

    Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种工具: SLF4J Apache Commons Logging Log4j 2 Log4j JDK logging 具体选择哪个日志 ...