Java中的==和equals区别

在学习Java中==和equals的区别时,有了自己的一个理解,特此分享,欢迎各位小伙伴们针对此文发表自己的意见!

在看别人这方面的博客时,感觉反正就是很乱,而且要看很多篇文章才能了解==~ 和equals区别的本质。但是,看了十几篇文章以后,突然感觉所有的知识都串起来了。以下就十几篇文章的内容进行了总结。
本文从Java的数据类型(基本数据类型和引用数据类型)、Java基本数据和引用数据的存储地方(多为栈和堆)、栈和堆的数据是否共享进行多视角的分析。带大家了解以上三方面的内容后,再来分析equals和==区别。

多视角分析1-Java的数据类型

java中的数据类型分为两类:

  • 基本数据类型–byte,short,char,int,long,float,double,boolean
  • 引用数据类型–接口、类、数组等非基本数据类型。

多视角分析2-Java基本数据和引用数据的存储地方

存储地方一般为栈和堆,特殊的不在栈和堆中,如常量池

  • 栈和堆中存储 如下面的代码所示:
    int i=2;
    String str =new String( “A”);
    其中,2和“A”分别代表基本数据和引用数据,在计算机中如何存储呢?
    首先,2和“A”都是数据,想一下,对于一个数据来说,能不能只存数据的值,如2(在计算机用二进制表示为00000010),这样是不行的。只存值,内存里存了这么多东西,怎么找到他们呢。这就需要内存来存储2(0000 0010)的地址。
    有人说了,那i又怎么找到2(0000 0010)的地址?
    实际上,对于i来说,你看的是i,编译器看的就是一个地址。就像网站访问,让你记IP地址是不可能的,但是记域名就简单了,中间DNS服务器负责给你转换。这个和网站访问是类似的。你只需要把i看成是一个地址就行了。
    总之,Java数据在计算机中都会存放两个属性:地址、值

    大多Java数据(String str=“abc”不一样,后面会讲)的地址和值存储在栈和堆中,那么,基本数据和引用数据的地址和值在栈和堆中如何存储的? 如下面的代码所示:
    int i=2;
    String str =new String( “A”);
    其中,
    基本数据地址和值的存储: int i=2(00000010); 地址i和值2(0000 0010)都存储在栈中。
    引用数据地址和值的存储: String str =“A”(在计算机中的二进制表示); str指代的地址存储在栈中,而“A”( 在计算机中的二进制表示)存储在堆中。

  • 常量池 前面讲到存储地方一般为栈和堆,特殊的就不存放在栈和堆中,如存放在常量池
    :对于直接赋值的字符串类型,如String str=“abc”,“abc”值存放在String池(常量池)中,“abc”的地址存放栈中。该类型的数据值在String池中是共享的,即若有String str=“abc”、String str1=“abc”,存放“abc”内容的内存只有一块,地址为X,str和str1别名对应的内存中存放的地址是相等的,都等于X)

总结:对于数据值,如2(0000 0010)来说,能够被共享是很节省内存空间的事情,栈和堆肯定也有是否共享的机制,如下

多视角分析3-栈和堆的数据值是否共享

  • :栈有一个很重要的特殊性,即存在栈中的数据值可以共享。如:
    同时定义:
    int a=3;
    int b=3;
    编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b =3;在创建完b这个引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况,即栈中就只有一块存放3(00000011)的内存。 基本数据类型的数据值是存放在栈中的,所以可以共享,因此,a和b的地址是相等的。
  • :如:
    Rectangle r1= new Rectangle(3,5);
    Rectangle r2= new Rectangle(3,5);
    Rectangle r3= new Rectangle(4,6);
    编译器先处理Rectangle r1=new Rectangle(3,5);首先它会在栈中创建一个变量为r1的引用,然后开辟一个存放new Rectangle(3,5)这个对象内容(即值)的地址,然后将r1指向new Rectangle(3,5)的地址;
    接着处理Rectangle r2= new Rectangle(3,5);首先它会在栈中创建一个变量为r2的引用,然后再开辟一个存放new Rectangle(3,5)这个对象内容(即值)的地址,然后将r2指向new Rectangle(3,5)的地址。这样,就出现了r1与r2指向不同地址下的new Rectangle(3,5)对象内容。实际上,不同地址存放的对象内容完全一样;
    接着处理Rectangle r3= new Rectangle(4,6); 首先它会在栈中创建一个变量为r3的引用,然后开辟一个存放new Rectangle(4,6)这个对象内容(即值)的地址,然后将r3指向new Rectangle(4,6)的地址。
    这时候,r2与r3指向不同地址,两个地址存放的对象内容也不一样。

总结:存放在堆中的引用数据类型的数据值不共享,因此,可能存在两个引用数据地址不一样,但是引用的内容是相等的。

进入正题:

equals和==比较的是值or地址呢?

对于基本数据类型byte,short,char,int,long,float,double,boolean而言:

  • equals:本质上equals不对基本数据类型进行比较。若强制使用equals对基本数据类型比较(即equals的参数是基本数据类型),自动封装方法可以做到。即先会进行自动装箱,基本型转换为其封装类型,再进行比较,如Integer(其值的范围在-128至127)。其本质上还是只对引用数据类型进行比较。
  • ==:比较的是值

对于引用数据类型而言:

  • equals:类Object是类层次结构的根类。每个类都使用Object作为超类。所有对象(包括数组)都实现这个类的所有方法。Object中有equals方法,因此除了Object之外的内都实现了equals方法,可对该方法选择覆盖或者不覆盖。
    在这里插入图片描述
    1. 不重写equals方法,则equals比较的是地址,如StringBuffer
    2. 重写equals方法,则比较的是值,即两个对象的内容,如String。
  • ==:比较的是地址
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值