Java 的 equals 和 ==
来源:互联网 发布:mysql 一周内 编辑:程序博客网 时间:2024/05/29 19:02
Java 的 equals 和 ==
引言
在 Java 编程中,我们常会用 equals 方法或 == 运算符来比较两个东西是否相等,若相等则返回 true,否则返回 false。
那么他们是如何工作的呢,下面来细说一下。
== 比较运算符
首先说说 == 这个比较运算符,他可以作用于对象变量也可以作用于基本类型的变量,那么是对于这两种类型,分别是如何工作的呢。
作用在引用变量上
先看如下代码:
public static void test() { Object obj1 = new Object(); Object obj2 = new Object(); System.out.println(obj1 == obj2); String s1 = "hello"; String s2 = "hello"; String s3 = new String("hello"); System.out.println(s1 == s2); System.out.println(s1 == s3); Integer i1 = 1; Integer i2 = 1; Integer i3 = new Integer(1); Integer i4 = 128; Integer i5 = 128; int i6 = 128; System.out.println(i1 == i2); System.out.println(i1 == i3); System.out.println(i4 == i5); System.out.println(i6 == i5);}
输出结果:
false true false true false false true
相信大家都知道,当使用 == 比较符作用于两个引用变量上时,当两个引用变量是指向同一个对象时,它则会返回 ture;否则返回 false;不过这实际上比较的是引用变量的保存的对象地址是否相等(引用变量保存的是对象的地址)
下面分析作用不同类型的对象时的表现
普通 obj 对象
在前面的例子中,obj1 和 obj2 比较,因为它们不是同一个对象,保存的地址也不同,因此返回 false。
String 对象
s1、s2 和 s3 比较,他们的内容都是 hello,但前者比较返回 true,而后者比较返回 false。原因主要是两者定义的方式不同,字符串在堆中存在一个字符串常量池,对于编译期能确定的字符串,都会在常量池中保存该常量,因此 s1,s2 实际上引用的都是常量池的常量,因此他们返回 true。而对于 s3,它是运行时创建的,因此是一个新对象,与 s1 引用的对象不是同一个对象,因此比较返回 false。
包装对象
包装对象 Integer 类的比较,i1 和 i2 是通过自动装箱的方式进行的,即它会调用 valueOf 方法来创建 Integer 对象,我们来看看 valueOf 方法的实现。
public static Integer valueOf(int i) { if (i >= IntegerCache.low && i <= IntegerCache.high) return IntegerCache.cache[i + (-IntegerCache.low)]; return new Integer(i);}
从方法里面可以看出,Integer 中也实现了一个缓冲池(对于 Boolean、Character、Byte、Short、Long 内部也采用了缓冲池,而 Float 和 Double) 则没有,当 i 位于缓冲池中(默认是 -128 ~ 127),则直接返回缓冲池中的对象实例,否则创建一个新实例。
创建 i1 和 i2 时,i 为 1,在缓冲池的范围内,因此它们都指向缓冲池的同一个对象,因此返回 true;i3 则是使用 new 来创建的新对象,因此比较返回 false;i4 和 i5 因为 i = 128 不在缓冲池的范围内,因此都是 不同的对象,所以返回 false;i6 是基本类型,与 i5 进行比较时,i5 会自动拆箱成基本类型,因此两个 int 都为 128 的变量是相等的,返回 true。
作用于基本类型变量
先看如下代码:
public static void baseTest() { byte b = 2; short s = 2; int i = 2; long l = 2l; float f = 2.0f; double d = 2.0; System.out.println(b == s); System.out.println(s == i); System.out.println(i == l); System.out.println(i == f); System.out.println(i == d); System.out.println(l == i); System.out.println(l == f); System.out.println(l == d); System.out.println(f == d);}
输出结果:
都是 true
使用 == 运算符作用于基本类型时,当比较的是相同类型变量时,会直接比较值的大小;但作用于不同类型的变量时,会发生隐式类型转换,转换成大类型,然后继续比较值。
类型转换的规则:
equals 方法
equals 方法也是用于比较两个对象是否相等,每一个 Object 对象都有它的 equals 方法,在 Object 类的默认实现如下:
public boolean equals(Object obj) { return (this == obj);}
当然子类也可以通过重写该方法来设计对象相等的规则,一般来说重写 equals 方法,也必须重写对象的 hashcode 方法。
从 Object 的源码可知,若子类没有重写 equals 方法,则若两个对象不是同一个对象,则会返回false;那么我们现在来分析一下 Java 类库中,一些常用对象的 equals 方法是如何工作的。
String 对象
先看如下代码:
public static void testString() { String s1 = "hello"; String s2 = new String("hello"); System.out.println(s1.equals(s2));}
输出结果:
true
从前面分析 == 运算符时,我们知道 s1 和 s2 不是同一个对象,但是它们的 equals 方法却返回true 了,现在我们来看看 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;}
从源码可以看出,若两个对象是同一个对象,仍然会返回 ture;若不是时,首先通过 instanceof 运算符判断是否是 String 对象,若是则会对 String 变量的底层数组进行比较,若数组的元素值都一样(即字符串一样),则会返回true,反之返回 false。
包装对象
先看如下代码:
public static void test() { Byte b = new Byte((byte)1); Short s = new Short((short)1); Integer i1 = 1; Integer i2 = new Integer(1); Long l = new Long(1); Float f = new Float(1); Double d = new Double(1); System.out.println(b.equals(i1)); System.out.println(s.equals(i1)); System.out.println(i1.equals(i2)); System.out.println(i1.equals(1)); System.out.println(l.equals(f)); System.out.println(f.equals(d));}
输出结果:
falsefalsetruetruefalsefalse
包装类型的 equals 方法,都是先用 instanceof 运算符判断是否是对应的包装类型,若是,则判断值是否相等,相等则返回 true;否则返回 false。
总结
对于 == 和 equals 方法,都是用于比较两个变量是否相等。== 可用于比较引用变量,也可用于比较基本类型变量。当用于比较引用变量时,比较的是两个变量是否引用同一个对象;基本类型比较的是值是否相等,当类型不一致时,会发生隐式类型转换。
equals 方法是 Object 的基本方法,默认实现是当两个对象不是同一个对象,则会返回 false。另外可以通过重写 equals 方法来更改对象相等的原则。如:String 的 equals 方法会比较底层字符数组的内容是否相等,包装类则会先通过 instanceof 运算符来判断是否同一种包装类型,再比较值是否相等。一般来说,重写了对象 equals 方法,最好也重写对象的 hashcode 方法,Java 类库的 Hash 实现是依赖于这两个方法来实现的。
- java ==和equals、equals和hashCode的区别
- Java的equals和==
- Equals和==的区别,java
- java == 和 equals的区别
- java ==和equals的区别
- java equals和==的详解
- Java "equals"和"=="的区别
- java:equals 和 ==的区别
- Java equals和==的用法
- Java的equals和==问题
- Java 的==和equals比较
- Java:的“==”和equals方法
- 谈谈java的"=="和equals
- Java "==" 和 .equals()的区别
- java == 和equals的区别
- java==和equals()的区别?
- java equals和==的区别
- java-==和.equals()的区别
- Queue模块
- 论文理解(一)树形lstm
- 5分钟从零搭建一个maven工程
- C动态内存分配:(三)malloc/calloc/realloc/free使用注意事项
- 编写高质量代码——Web前端开发修炼之道(一)
- Java 的 equals 和 ==
- Windows64位机使用RXTX开源包的安装和环境配置
- C++设计模式之单例模式
- Java静态属性与静态方法能否被继承的问题
- webService【一】
- 简单的Java Web项目(2)——session实现简单的购物车
- GDUT2017校赛:Problem C: 爬楼梯(DP)
- 解决hbase时间不同步问题
- Android Asytask详解