JAVA- 浅谈==与equal()的区别

目录

>基础

>基本数据类型

>引用数据类型

>Java内存

>区别==和equals()

 >==

>equals()

>总结


>基础

要想区分这两者,我们得先明白什么是基本数据类型和引用数据类型,以及Jav的内存构成

>基本数据类型

这八种数据变量中直接存储值。

>引用数据类型

引用数据类型非常多,大致包括:
类、 接口类型、 数组类型、 枚举类型、 注解类型、 字符串型

例如,String类型就是引用类型。
简单来说,所有的非基本数据类型都是引用数据类型。

>Java内存

Java内存模型中存在这两种内存区域:一种是栈内存,一种是堆内存。 (注:程序计数器,运行时数据区,永久代,直接内存这里不讨论,因为java对象保存在栈内存(基本数据类型)和堆内存(引用数据类型和包装类)中

在函数中定义的一些基本类型的变量和对象的引用变量(变量名)都在函数的栈内存中分配。

当一段代码块定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。

栈只是存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符串常量对象存放在常量池中。)

堆内存用来存放由new创建的对象(包括由基本类型包装起来的类:Integer、String、Double,实际上每个基本类型都有他的包装类)和数组。

>区别==和equals()

 ==比较的是两个对象的地址,而equals比较的是两个对象的内容。

举个通俗的例子来说,
==是判断两个人是不是住在同一个地址
而equals是判断同一个地址里住的人是不是同一个

 >==

1)对于基本数据类型的变量, ==是直接对其值进行比较
2)对于引用数据类型的变量,则是对其内存地址的比较

下面来看一个有趣的例子:

public class deng {
    public static void main(String[] args) {
        Integer a =100;
        Integer b =100;
        Integer c =1000;
        Integer d =1000;
        System.out.println(a==b); //true
        System.out.println(c==d); //false
    }
}

这是因为Integer对象除了可以通过new来创建,也可以直接将int值赋给Integer变量,系统会自动将这个int值封装成一个Integer对象。
如:Integer a = 100;实际上的操作是:Integer a = Integer.valueof(100);

high的值为127,low的值为-128,当进行这个方法时如果值在-128-127之间,返回的值也就是地址是相同的.

这里有一个需要注意的地方:在上面Integer的valueof()方法里面,当int值范围在-128—127之间时,会通过一个IntegerCache缓存来创建Integer对象;当int值不在该范围时,直接调用new Integer()来创建对象。因此会产生以下情况:

(1)Integer a = 100;Integer b = 100;a == b为True。
因为这两个Integer变量引用的是缓存中的同一个Integer对象。

(2)Integer c = 1000; Integer d = 1000;c == d为False。
这似乎因为这两个Integer变量引用的是通过new创建的两个不同对象。

>equals()

1)基本类型不是对象,所以没有equals方法。
2)对于引用数据类型的变量,则是对其内容的比较

我们知道任何类都继承Object类,这里我们先看下object类里的equals方法:

我们可以从这段源码看出,在没有重写equals方法之前,equals方法里是直接调用==,因此实质上与==没有差别。但是要注意:equals方法不能作用于基本数据类型的变量,这是因为基本数据类型非对象的缘故,没有方法。

然而,在一些类库当中这个方法被重写了比如String 、Date、ArrayList等类,这样就不在是去比较在堆内存中的存放地址了。这里我们可以看下String类里equals方法的重写: 

从上面可以看出,先用==判断对象的地址是否相等,相等则返回true。

       如果前面的判断不成立,接着判断括号内的对象上是否是String类型,接着判断两个字符串对象的的长度是否相等,最后判断内容是否相等,如果相等则返回true。

再来一道例题测试一下吧~

public class deng {
    public static void main(String[] args) {
        String s1,s2;
        s1 = new String("嗯");
        s2 = new String("嗯");
        System.out.println(s1.equals(s2));  //true
        System.out.println(s1==s2);         //false
        String s3,s4;
        s3 = "嗯";
        s4 = new String("嗯");
        System.out.println(s3.equals(s4));  //true
        System.out.println(s3==s4);         //false
        String s5,s6;
        s5 = "嗯";
        s6 = "嗯";
        System.out.println(s5.equals(s6));  //true
        System.out.println(s5==s6);         //true
    }
}

>总结

1)对于==,一般比较的是值是否相等
     如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
     如果作用于引用类型的变量,则比较的是所指向的对象的地址

2)对于equals方法,一般为比较内容是否相同
     如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
     诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的地址/内容。

3)若 == 为true,则equals必为true
     若equals为false,则 == 必为 false

  • 7
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值