java中==和equals的区别
一、理解"=="的含义
在java中,主要有两个作用:
1、基本数据类型:比较的是他们的值是否相等,比如两个int类型的变量,比较的是变量的值是否一样。
其中基本数据类型有8个:byte(8位)、short(16位)、int(32位)、long(64位)、float(32位)、double(64位)、char(16位)、boolean(true和false)。
八大基本数据类型对应着各自的封装类型,提供了更多的方法,且不进行初始化时,值默认为空(基本数据类型必须初始化)。
2、引用数据类型:比较的是引用的地址是否相同,比如说新建了两个User对象,比较的是两个User的地址是否一样。
OK。到这就注意了,你会发现,我在举引用的例子的时候,使用的是User对象,而不是String。别着急接着往下看。
二、理解equals的含义
先看看他的源码,equals方法是在Object中就有的,注意了这里的源码是Object里面的equals。
从这个源码中你会发现,比较的是当前对象的引用和obj的引用是否相同,也就是说比较的默认就是地址。还记的在上面我们使用的是User而不是String嘛?在这里==比较的是引用的地址,equals也是比较的是引用的地址,所以他们的效果在这里是一样的。
现在你会发现好像equals的作用和==没什么区别呀,那String类型那些乱七八糟的东西是什么呢?继续往下看马上揭晓。
三、重写equals
1、String中equals方法:
Object对象里面的==和equals没有什么区别,这样一看equals方法存在的意义真的不大,不过后来String在Object的基础之上重写了equals,于是功能被大大的改变了。如何重写的呢?我们去String的源码中找寻答案:
从上面的源码,我们能够获取到的信息是:String中的equals方法其实比较的是字符串的内容是否一样。也就是说如果像String、Date这些重写equals的类,你可要小心了。使用的时候会和Object的不一样。
2、测试String:
看看下面的代码:
在上面的代码中,定义了三个字符串,分别使用==和equals去比较。为什么会出现这样一个结果呢?还需要从内存的角度来解释一下。
3、内存解释:
在java中我们一般把对象存放在堆区,把对象的引用放在栈区。因此上面三个字符串的内存状态应该是下面这样的。
现在明白了:
(1)String str1 = "Hello"会在堆区存放一个字符串对象
(2)String str2 = new String("Hello")会在堆区再次存放一个字符串对象
(3)String str3 = str2这时候Str3和Str2是两个不同的引用,但是指向同一个对象。
根据这张图再来看上面的比较:
(1)str1 == str2吗?意思是地址指向的是同一块地方吗?很明显不一样。
(2)str1 == str3吗?意思是地址指向的是同一块地方吗?很明显不一样。
(3)str2 == str3吗?意思是地址指向的是同一块地方吗?很明显内容一样,所以为true。
(4)str1.equals(str2)吗?意思是地址指向的内容一样吗?一样。
(5)str1.equals(str3)吗?意思是地址指向的内容一样吗?一样。
(6)str2.equals(str3)吗?意思是地址指向的内容一样吗?一样。
4、总结:
(1)基本类型比较:
①使用双等号 == 比较的是值是否相等。
②基本数据类型无equals方法(没有意义)。
(2)引用类型比较:
①重写了equals方法,比如String。
第一种情况:使用==比较的是String的引用是否指向了同一块内存。
第二种情况:使用equals比较的是String的引用的对象内用是否相等。
②没有重写equals方法,比如User等自定义类。
==和equals比较的都是引用是否指向了同一块内存。
5、一个小问题:
当然了,String类型到这还没结束,有一个小问题需要大家注意一下。比如看下面的代码:
在这里多了一个intern方法。他的意思是检查字符串池里是否存在,如果存在了那就直接返回为true。因此在这里首先s1会在字符串池里面有一个,然后 s2.intern()一看池子里有了,就不再新建了,直接把s2指向它。