java中equals合if的用法_java中equals与==的用法浅析

说到java中的equals与==的用法,这里首先梳理一下java中的数据类型,主要分为两大类:值类型和引用类型,值类型也就是基本数据类型,而引用类型就是除了值类型之外的其他类型。

基本数据类型(8种):byte、short、int、long、float、double、char、boolean

引用类型(3种):类(Class)类型、接口(Interface)类型、数组(Array)类型

1.equals用法总结

个人的归纳如下:

在Object类中定义了一个原始的equals方法,这个方法的行为是比较引用变量中存储的对象在堆内存中的地址,使用“==”实现。

在一些类库当中equals方法被重写了,如String、包装类、Date等等。在这些类当中equals有其自身的实现,而不再是比较对象在堆内存中的存放地址了。

对于引用类型之间进行equals比较,在没有重写equals方法的情况下,他们之间的比较还是堆内存中的存放的地址值,跟双等号(“==”)的结果相同;如果被重写,则按照重写的要求来进行比较。

equals方法不能用于基本数据类型的比较,但是能够用于基本类型的包装类,并且比较的是对象的内容而不是地址。

下面给出一些源码来进一步理解:

1 //Object类中的equals方法

2 public booleanequals(Object obj) {3 return (this ==obj);4 }5

6 //String类中的equals方法,重写了Object类的equals方法

7 public booleanequals(Object anObject) {8 if (this ==anObject) {9 return true;10 }11 if (anObject instanceofString) {12 String anotherString =(String)anObject;13 int n =value.length;14 if (n ==anotherString.value.length) {15 char v1[] =value;16 char v2[] =anotherString.value;17 int i = 0;18 while (n-- != 0) {19 if (v1[i] !=v2[i])20 return false;21 i++;22 }23 return true;24 }25 }26 return false;27 }28

29 //Integer类中的equals方法,重写了Object类的equals方法,其他包装类也重写了equals方法

30 public booleanequals(Object obj) {31 if (obj instanceofInteger) {32 return value ==((Integer)obj).intValue();33 }34 return false;35 }36

37 //Date类中的equals方法,重写了Object类的equals方法

38 public booleanequals(Object obj) {39 return obj instanceof Date && getTime() ==((Date) obj).getTime();40 }

因此,当且仅当调用的是Object类的equals方法时,equals与“==”的作用相同,比较的是对象在堆内存中的地址;而当调用的是其他类重写过后的equals方法时,通常来说比较的是对象的内容而不是地址。具体示例如下:

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

1 /*

2 * StringBuffer和StringBuilder类都没有重写equals方法3 * 所以此处调用的是Object类的equals方法,比较的是地址4 */

5 StringBuffer buffer1 = new StringBuffer("hello");6 StringBuffer buffer2 = new StringBuffer("hello");7 System.out.println(buffer1.equals(buffer2));//false

8 System.out.println(buffer1 == buffer2);//false

9

10 /*

11 * String类重写了Object类的equals方法12 * 所以此处调用的是String类的equals方法,比较的是内容13 */

14 String s1 = "hello";15 String s2 = "hello";16 String s3 = new String("hello");17 String s4 = new String("hello");18 System.out.println(s1.equals(s2));//true

19 System.out.println(s1.equals(s3));//true

20 System.out.println(s3.equals(s4));//true

21

22 /*

23 * Integer包装类重写了Object类的equals方法24 * 所以此处调用的是Integer类的equals方法,比较的是内容25 */

26 Integer integer = new Integer(100);27 System.out.println(integer.equals(new Integer(100)));//true

View Code

2.==用法总结

双等号(“==”)是一种关系运算符,它的用法比较简单,主要分为两种情况:

用于基本数据类型之间的比较:比较的是变量的值(注意此时不一定要求“==”左右两边数据类型严格一致)

用于引用类型之间的比较:比较的是引用对象在堆内存中的地址

这里简单举了几个例子:

1 //基本数据类型的比较

2 int a=10, b=10;3 char ch1='A', ch2='A';4 System.out.println(a == b);//true

5 System.out.println(ch1 == ch2);//true6

7 //引用类型的比较

8 Object o1 = newObject();9 Object o2 = newObject();10 Object o3 =o1;11 System.out.println(o1 == o2);//false

12 System.out.println(o1 == o3);//true

1 int c = 65;2 float d = 65.0f;3 char ch = 'A';4

5 /*

6 * 用于基本数据类型之间,比较的是变量的值7 * 注意:此时不一定要求数据类型严格一致8 */

9 System.out.println(c == d);//true

10 System.out.println(c == ch);//true

11 System.out.println((d == ch));//true

3.对比分析

我们常常弄不明白equals与==的用法,是因为我们没有结合JDK源码系统地总结过它们,这里先抛出一段代码:

1 String s1 = "hello";2 String s2 = "hello";3 String s3 = new String("hello");4 String s4 = new String("hello");5 System.out.println(s1.equals(s2));//true

6 System.out.println(s1 == s2);//true

7

8 System.out.println(s1.equals(s3));//true

9 System.out.println(s1 == s3);//false

10

11 System.out.println(s3.equals(s4));//true

12 System.out.println(s3 == s4);//false

有了之前的一些学习,我们来分析一下这段代码:

由于这里的对象都是String类型,所以调用的都是String类的equals方法,比较的是字符串的内容,所以结果都是true。

然而,代码的第6行中,“==”比较的是两个引用变量s1和s2所指向的对象的地址,结果为true;而第12行,这里的“==”比较的也是两个引用变量s3和s4所指向的对象的地址,结果为false。

那么为什么第6行和第12行的结果不相同呢?

这就涉及到字符串常量的两种创建方式“String s1 = "hello"”和“String s3 = new String("hello")”的区别了,这里用一个图来说明:

1e835270d82b5760ed118a70a286cf7f.png

通过上图,我们对于这两种字符串常量的创建方式可以总结如下:

通过“String s1 = "hello"”方式创建的话,JVM要先检查常量池中是否已经包含有“hello”,若有,则将其地址赋给s1;否则将字符串常量“hello”存储在常量池中,并返回存储地址;

通过“String s3 = new String("hello")”创建,JVM需要先在堆中开辟一段空间用于存储new出来的对象,又由于“hello”是一个字符串常量,所以需要将其放在常量池中,并返回其存储地址。

因此,对于代码中第6行的“s1 == s2”,由于s1与s2都指向的是字符串常量池中“hello”的地址,所以结果为true;而对于第12行的“s3 == s4”,由于s3与s4指向的是堆中的两个不同的对象,所以结果为false。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值