写这篇文章的目的是自己彻底把三者搞清楚,也希望对你有所帮助。

1."=="运算符对与基本类型(int long float double boolean byte char short),比较的是他们的值。但是对于复合数据类型,比较的是他们的内存地址。

public class TestString {
public static void main(String[] args){
String s1="Hello";
String s2="Hello";
if(s1==s2){
System.out.println("s1==s2");
}else{
System.out.println("s1!=s2");
}
} }

运行结果 s1==s2

public class TestString {
public static void main(String[] args){
String s1=new String("Hello");
String s2=new String("Hello");
if(s1==s2){
System.out.println("s1==s2");
}else{
System.out.println("s1!=s2");
}
} }

运行结果 s1!=s2

分析:

当我们用String s1="Hello",再创建String s2="Hello"的时候,他会先去字符串缓冲池寻找相同的对象,因为我们之前创建了s1,s1被放在了字符串缓冲池中,

所以s2创建的时候,就找到了相同的值s1,s1和s2指向同一个对象。

当我们使用new的时候,就会新开辟一个内存地址,无论你怎么比较都不会相等的。

public class TestString {
public static void main(String[] args){
String s1="Hello";
String s2=new String("Hello");
if(s1==s2){
System.out.println("s1==s2");
}else{
System.out.println("s1!=s2");
}
} }

所以这个比较结果返回的也是s1!=s2,因为当我们用String s1="Hello"的时候,这个时候字符串缓冲池存在值Hello,但是接下来String s2=newString("Hello");他会怎么办呢,他会先去字符串缓冲池去找,如果池子没有Hello,他会在字符串缓冲池创建一个字符串常量“Hello”,如果存在就不在字符串缓冲池中创建。然后会在堆中创建一个新的对象(无论字符串缓冲池有没有都会执行)。所以说两者内存地址不相等。

2.equals是Object基类中的一个方法,java中所有的类都是继承Object 这个基类的。这个方法初始也是比较两者的内存地址的,这是原始的Object中的equals方法源码

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

很明显的看到方法里面的==,说明比较的是内存地址。

但是有一些类中有自身的equals方法把原本的方法覆盖掉了,就不再是比较两者的内存地址了,而是比较的内容值,例如String中的equals源码

 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类型逐一比较内容值。

public class TestString {
public static void main(String[] args){
String s1="Hello";
String s2=new String("Hello");
if(s1.equals(s2)){
System.out.println("s1==s2");
}else{
System.out.println("s1!=s2");
}
} }

结果返回:s1==s2。

注意:那这样的代码又会返回什么结果呢?

public class TestString {
public static void main(String[] args){
String s1="Hello";
String s2=new String("Hello");
s2=s2.intern();
if(s1==s2){
System.out.println("s1==s2");
}else{
System.out.println("s1!=s2");
}
} }

返回结果:s1==s2。为什么??答案:String#intern方法,这个方法是一个 native 的方法,“如果常量池中存在当前字符串, 就会直接返回当前字符串. 如果常量池中没有此字符串, 会将此字符串放入常量池中后, 再返回”。

3.hashCode方法也是从Object类中继承过来的,它是用来鉴定两个对象是否相等,Object类中的的hashCode返回的是对象在内存中地址转换成的一串int数值,如果没有重写hashCode方法,任何对象的hashCode都不会相等的。恰恰String的hashcode重写了,你说气人不。如果两个对象equals相等,则hashCode必须相等,反之不成立。一般来说你重写了equals,也要重写HasCode。

"==" equals和hashCode的联系和区别的更多相关文章

  1. ==、equals()、hashcode()的关系和区别

    ==.equals().hashcode()概念 ==:它的作用是判断两个对象的地址是不是相等.即,判断两个对象是不试同一个对象. equals():它的作用也是判断两个对象是否相等.但它一般有两种使 ...

  2. Java中==、equals、hashcode的区别与重写equals以及hashcode方法实例(转)

    Java中==.equals.hashcode的区别与重写equals以及hashcode方法实例  原文地址:http://www.cnblogs.com/luankun0214/p/4421770 ...

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

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

  4. ==、equals、hashCode区别?

    [==.equals().hashCode()区别?] 1)== 运算符用来比较两个变量的值是否相等. 即该运算符用于比较变量对应得内存中所存储的数值是否相同,要比较两个基本类型的数据或两个引用变量是 ...

  5. Java == ,equals 和 hashcode 的区别和联系(阿里面试)

    今天阿里的人问我 equals 与hashcode的区别,我答不上来, 仔细查了一下,做了总结: (1) == 这是Java 比较内存地址,就是内存中的对象: java中的==是比较两个对象在JVM中 ...

  6. 深入理解equals和hashCode关系和区别

    为什么要说equals和hashCode这两个东西,一来是因为有不少小伙伴面试时被问过这个东西,二来则是因为如果了解了这两个东西的原理,那么实际的开发过程中,对效率和容错率上还是能帮上很大的忙! 直入 ...

  7. equals与hashCode的区别

    equals与hashCode的区别 1.类中的equals方法是一定要重写/覆盖(Override)的,因为要让它按照设计的需求来根据特征值判断等价性. 这里的特征值,就是String类型的name ...

  8. 【转】Java中==、equals、hashcode的区别与重写equals以及hashcode方法实例

    原文地址:http://www.cnblogs.com/luankun0214/p/4421770.html 感谢网友的分享,记录下来只为学习. 1.重写equals方法实例   部分代码参考http ...

  9. java ==、equals、hashcode有什么区别

    1.== 用来比较两个对象的存储空间 2.equals是Object类提供的方法之一,每个java类都继承Object类,所以每一个对象都具有equals方法,所以在没有覆盖equals方法的情况下, ...

随机推荐

  1. Android so 文件进阶<三> so文件的简单加密

    0x00  前言 之前的两篇文章从链接视图和执行视图分析了elf文件的大致结构,这篇文章主要内容是对于so文件进行简单的加密工作,针对Ida等静态分析工具的分析,一旦开始动态调试就应该很容易就可以du ...

  2. Docker Swarm 日常运维命令笔记

    之前介绍了Docker管理工具-Swarm部署记录,这里简单总结下Docker Swarm的日常维护命令,以作为平时运维笔记. Swarm作为一个管理Docker集群的工具,首先需要将其部署起来,可以 ...

  3. superset--presto sql

    1.hive的partition的相关查询,由于presto不支持vachar和int的自动转换,所以使用where的时候需要手动转换一下. #select count(*) from userlog ...

  4. JSONPath使用说明

    # JSONPath - XPath for JSON A frequently emphasized advantage of XML is the availability of plenty t ...

  5. C# Owin初探 概念理解(一)

    本文是阅读网上大牛的文章总结而成. 目录 1.Owin定义 2.为什么要用Owin 3.作用 4.总结 1.Owin定义 Owin是Open Web Interface For .NET.也就是.Ne ...

  6. C#winform使用进度条

    在用c#做WinFrom开发的过程中.我们经常需要用到进度条(ProgressBar)用于显示进度信息.这时候我们可能就需要用到多线程,如果不采用多线程控制进度条,窗口很容易假死(无法适时看到进度信息 ...

  7. 深入贯彻闭包思想,全面理解JS闭包形成过程

    谈起闭包,它可是JavaScript两个核心技术之一(异步和闭包),在面试以及实际应用当中,我们都离不开它们,甚至可以说它们是衡量js工程师实力的一个重要指标.下面我们就罗列闭包的几个常见问题,从回答 ...

  8. 37.Linux驱动调试-根据oops的栈信息,确定函数调用过程

    上章链接入口: http://www.cnblogs.com/lifexy/p/8006748.html 在上章里,我们分析了oops的PC值在哪个函数出错的 本章便通过栈信息来分析函数调用过程 1. ...

  9. Java多线程--JDK并发包(2)

    Java多线程--JDK并发包(2) 线程池 在使用线程池后,创建线程变成了从线程池里获得空闲线程,关闭线程变成了将线程归坏给线程池. JDK有一套Executor框架,大概包括Executor.Ex ...

  10. 编程输出杨辉三角的前10行---多维数组的应用---java实现

    import java.util.Scanner;public class yanghui{ public static void main(String[] args){  Scanner sc=n ...