【Java学习笔记】equal与==

==

对于基本数据类型来说,主要是匹配值是否相同。

1
2
3
4
5
6
7
8
ini复制代码public class Equals {
   public static void main(String[] args) {
       int a = 1;
       int b = 1;
       System.out.println(a == b);
       System.out.println(b == a);
  }
}

输出结果如下:

1
2
arduino复制代码true
true

对于引用类型来说,==匹配的是两个是否指向了同一内存区域。

1
2
3
4
5
6
7
8
9
10
java复制代码public class Equals {

   static Person person1 = new Person();

   static Person person2 = new Person();

   public static void main(String[] args) {
       System.out.println(person1 == person2);
  }
}

上述通过new关键字分别创建了2个对象,此时我们用==进行比较,结果如下

1
arduino复制代码false

这里涉及到对象创建的只是了,后续在虚拟机相关笔记中体现。

equal

equals 是 Java 中所有对象的父类,即 Object 类定义的一个方法。它只能比较对象,它表示的是引用双方的值是否相等

1
2
3
4
5
6
7
8
9
csharp复制代码public class Equals {
   public static void main(String[] args) {
       Person person1 = new Person();
       Person person2 = new Person();
       person1.setName("1");
       person2.setName("1");
       System.out.println(person1.getName().equals(person2.getName()));
  }
}

equals 用作对象之间的比较具有如下特性

  • 自反性:对于任何非空引用 x 来说,x.equals(x) 应该返回 true。
  • 对称性:对于任何非空引用 x 和 y 来说,若x.equals(y)为 true,则y.equals(x)也为 true。
  • 传递性:对于任何非空引用的值来说,有三个值,x、y 和 z,如果x.equals(y) 返回true,y.equals(z) 返回true,那么x.equals(z) 也应该返回true。
  • 一致性:对于任何非空引用 x 和 y 来说,如果 x.equals(y) 相等的话,那么它们必须始终相等。
  • 非空性:对于任何非空引用的值 x 来说,x.equals(null) 必须返回 false。

String的equal实现

String也是在日常编程中经常使用的修饰符之一,它和其它基本数据类型不同,String本身是一个常量(final),其不能被其他对象所继承(至于原因,据说是开发者觉得String实现已经非常完美了,不想开发者任意扩展来破坏它),其一经赋值便无法再改变,继承自Object,所以Object具有的能力在String中都可以找到相对于的。

此处我们重点分析,String中的equal实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
arduino复制代码public boolean equals(Object anObject) {
   // 首先满足自反性,自己传入自己确保返回为true
   if (this == anObject) {
       return true;
  }
   // 确保传入的Object为String类型
   if (anObject instanceof String) {
       String anotherString = (String)anObject;
       int n = value.length;
       // 判断长度是否相等,如果不等一定为false
       if (n == anotherString.value.length) {
           char v1[] = value;
           char v2[] = anotherString.value;
           int i = 0;
           // 开始逐个字符比较,如果发现不相等的字符,则返回false
           while (n-- != 0) {
               if (v1[i] != v2[i])
                   return false;
               i++;
          }
           return true;
      }
  }
   return false;
}

String中equals的实现总结来说可以是以下几点:

1.判断是否传入的是自身,如果是返回true。

2.判断是否是String对象,如果不是返回true。

2.1 如果是String对象 则比较传入的len是否一致,如果一致,则继续比较。

2.2 比较字符,如果字符不一致,则返回false,反之继续比较直到比较完全(这里是一个循环全量匹配)

这里再提示一下,你可能有疑惑什么时候是

1
2
3
kotlin复制代码if (this == anObject) {
 return true;
}

这个判断语句如何才能返回 true?因为都是字符串啊,字符串比较的不都是堆空间吗,猛然一看发现好像永远也不会走,但是你忘记了 String.intern() 方法,它表示的概念在不同的 JDK 版本有不同的区分

在 JDK1.7 及以后调用 intern 方法是判断运行时常量池中是否有指定的字符串,如果没有的话,就把字符串的引用添加到常量池中,并不是复制一份对象放入其中了。

重写HashCode

equals 方法和 hashCode 都是 Object 中定义的方法,它们经常被一起重写。

equals 方法是用来比较对象大小是否相等的方法,hashcode 方法是用来判断每个对象 hash 值的一种方法。如果只重写 equals 方法而不重写 hashcode 方法,很可能会造成两个不同的对象,它们的 hashcode 也相等,造成冲突。比如

1
2
3
4
ini复制代码String str1 = "通话";
String str2 = "重地";
System.out.println(str1.hashCode());
System.out.println(str2.hashCode());

上述两个字符串所代表的hashcode就是相同的。

1
2
复制代码1179395
1179395

它们两个的 hashcode 相等,但是 equals 可不相等。

关于equals总结如下

  • 如果在 Java 运行期间对同一个对象调用 hashCode 方法后,无论调用多少次,都应该返回相同的 hashCode,但是在不同的 Java 程序中,执行 hashCode 方法返回的值可能不一致。
  • 如果两个对象的 equals 相等,那么 hashCode 必须相同
  • 如果两个对象 equals 不相等,那么 hashCode 也有可能相同,所以需要重写 hashCode 方法,因为你不知道 hashCode 的底层构造(后续可以解析jvm源码深入认识hashcode的构造),所以你需要重写 hashCode 方法,来为不同的对象生成不同的 hashCode 值,这样能够提高不同对象的访问速度。
  • hashCode 通常是将地址转换为整数来实现的。

参考文献:github.com/crisxuan/be…

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%