目录
相等判断符 "==" 介绍
"==" 判断基本类型是否相等.
"==" 判断引用类型数据是否相等
判断是否相等 - equals()方法介绍.
深入探究 equals(), 为什么会有 equals()方法?
相等判断符 "==" 介绍
"==" 相等判断符用于比较基本数据类型和引用类型数据. 当比较基本数据类型的时候比较的是数值, 当比较引用类型数据时比较的是引用(指针).
"==" 判断基本类型是否相等.
首先基本数据类型指的是 Java 中的八大数据类型: byte, short, int, long, float, double, char, boolean
这八大基本数据类型有个共同的特点是它们在内存中是有具体值的, 比如说一个 int 类型的数据 "2", 它在 8 位数据总线的机器上 (假设的) 保存形式为 0000 0010.
当使用 "==" 比较两个基本数据类型的时候, 就是比较它们各自在内存中的值.
"==" 判断引用类型数据是否相等
引用数据类型在字面上也是很好理解的, 就是一个引用, 它会指向一个具体的对象.
比如说
Student stu = new Student();
, 这里的 stu 就是一个引用, 它指向的是当前 new 出来的 Student 对象. 当我们想要操作这个 Student 对象时, 只需要操作引用即可, 比如说
- int age = stu.getAge();
- .
所以用 "==" 判断两个引用数据类型是否相等的时候, 实际上是在判断两个引用是否指向同一个对象.
看下面的示例
- public static void main(String[] args) {
- String s1 = "hello"; //s1 指向常量池中的 "hello" 字符串
- String s2 = "hello"; //s2 也指向常量池中的 "hello" 字符串
- System.out.println(s1 == s2); //true
- String s3 = new String("hello"); //s3 指向的是堆内存中的字符串对象
- System.out.println(s1 == s3); //false
- }
从上面的例子可以看到, 由于引用 "s1" 和 "s2" 指向的都是常量池中的 "hello" 字符串, 所以返回 true.
而 "s3" 指向的是新创建字符串对象, 因为只要动用了 new 关键字, 就会在堆内存创建一个新的对象,
也就是说 s1 和 s3 指向的是不同的字符串对象, 所以返回 false.
判断是否相等 - equals()方法介绍.
equals()和 == 有着本质的区别, == 可以看作是对操作系统比较数据手段的封装, 而 equals()则是每个对象自带的比较方法.
equals()和 == 的本质区别更通俗的说法是, == 的比较规则是定死的, 如上面所述; 而 equals()的比较规则是不固定的, 可以由用户自己定义.
看下面的例子:
- public static void main(String[] args) {
- String s1 = "hello";
- String s3 = new String("hello");
- System.out.println(s1.equals(s3)); //true
- }
在用 == 比较的时候, 上面 s1 和 s3 比较出的结果为 false. 而当用 equals 比较的时候, 得出的结果为 true.
想知道原因我们还得看源码, 下面是 String 类的 equals()源码.
- public boolean equals(Object anObject) {
- if (this == anObject) { // 先比较两个字符串的引用是否相等(是否指向同一个对象), 是直接返回 true
- 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;
- }
从上面的源码可以看到, 当调用 String 类型的 equals()方法时, 首先会判断两个字符串的引用是否相等, 也就是说两个字符串引用是否指向同一个对象, 是则返回 true.
如果不是指向同一个对象, 则把两个字符串中的字符挨个进行比较. 由于 s1 和 s3 字符串都是 "hello", 是可以匹配成功的, 所以最终返回 true.
深入探究 equals(), 为什么会有 equals()方法?
通过上面的讲解相信你已经知道 == 和 equals()的区别, 一个的比较规则是定死的, 一个是可以由编程人员自己定义的.
可是为什么会有 equals()方法, 而且还可以被自由定制呢?
这个问题要落到 Java 语言的核心 -- 面向对象思想了. Java 不同于面向过程的 C 语言, Java 是一款面向对象的高级语言. 如果只是面向过程, 直接操作内存上存储的数据的话, 用 == 所定义的规则来判断两个数据是否相等已经足够了.
而 Java 中处处是对象, 我们经常要面对的问题是这两个对象是否相等, 而不是这两串二进制数是否相等, 仅有 "==" 是完全不够用的.
考虑到编程人员会使用 Java 创建各种满足它们业务需求的对象, 系统无法提前知道两个对象在什么条件下算相等, Java 干脆把判断对象是否相等的权力交给编程人员.
具体的措施是: 所有的类都必须继承 Object 类, 而 Object 类中写有 equals()方法. 编程人员可以通过重写 equals()方法实现自己的比较策略, 也可以不重写, 使用 Object 类的 equals()比较策略.
- //Object 类中的 equals()方法源码
- public boolean equals(Object obj) {
- return (this == obj);
- }
从 Object 类的 equals()源码可以看到, 如果编程人员没有显示地重写 equals()方法, 则该类对象默认通过引用数据类型进行比较, 也就是说比较两个引用是否指向同一个对象.
补充: 关于基本数据类型包装类的比较
由于 Java 中万物皆对象, 就连基本数据类型也有其对应的包装对象, 那么它们对应的比较策略是什么呢?
- public static void main(String[] args) {
- int a = 3;
- Integer b = new Integer(3);
- System.out.println(b.equals(a)); //true, 自动装箱
- }
从上面的代码可以看到尽管两个引用不同, 但是输出的结果仍为 true, 证明 Integer 包装类重写了 equals()方法.
- //Integer 类中的 equals 方法
- public boolean equals(Object obj) {
- if (obj instanceof Integer) {
- return value == ((Integer)obj).intValue();
- }
- return false;
- }
从源码看到, 基本类型包装类在重写的 equals 方法中, 比较的还是基本数据类型的值.
来源: https://www.cnblogs.com/tanshaoshenghao/p/10896512.html