[关闭]
@frank-shaw 2015-10-31T11:11:00.000000Z 字数 2648 阅读 2557

equals方法和==的区别

java.基础知识


回答这个问题之前,首先需要弄清楚该变量类型是什么?

变量类型如果是值类型,那么它存储在内存中的虚拟机栈中。而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而被引用者本身则存储在堆中。

==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量在堆中存储的地址是否相同,即栈中的内容是否相同。

对于引用型变量,equals操作表示的两个变量所引用的对象是否相同,即堆中的内容是否相同(默认情况下Object.equals(),两个引用型变量一定要指向同一个对象,看看源码就知道了。但是其他类就不是这样子了,毕竟没个类都有不同的内容,还是需要跟内容来看是否相等的)。==比较的是2个对象的地址,而equals比较的是2个对象的内容。

实例

我们可以看一下一个很简单的代码,分析下面的Person类的equals()方法是怎样做判断的:

  1. class Person{
  2. private int age;
  3. private String name;
  4. public Person() {}
  5. public Person(int age, String name) {
  6. this.age = age;
  7. this.name = name;
  8. }
  9. @Override
  10. public boolean equals(Object obj) {
  11. //判断两个对象的内存地址是否相同,相同则返回真
  12. if (this == obj)
  13. return true;
  14. if (obj == null)
  15. return false;
  16. //判断两个对象是否是同一个类
  17. if (getClass() != obj.getClass())
  18. return false;
  19. //在判断得到两个对象是同一个类的基础上,进而来判断内容
  20. Person other = (Person) obj;
  21. if (age != other.age)
  22. return false;
  23. if (name == null) {
  24. if (other.name != null)
  25. return false;
  26. } else if (!name.equals(other.name))
  27. return false;
  28. return true;
  29. }
  30. }

可以看到,上面的equals()方法的判断中使用到了“==”,表示的是判断两个对象的地址是否相等。即使两对象不是同一个对象,那么也可以看看两个对象是否是同一个类,在同一个类的基础上,那么就可以比较其中的内容是否相等。这就是Person类判断是否相等的一个逻辑。在判断其中的内容是否相等的过程中,由于name 是String类,其用到了String类的equals()方法。接下来让我们来看看源代码String类的equals()方法是怎样的:

  1. public final class String
  2. implements java.io.Serializable, Comparable<String>, CharSequence {
  3. /** The value is used for character storage. */
  4. private final char value[];
  5. /** Cache the hash code for the string */
  6. private int hash; // Default to 0
  7. /** use serialVersionUID from JDK 1.0.2 for interoperability */
  8. private static final long serialVersionUID = -6849794470754667710L;
  9. /**
  10. * Class String is special cased within the Serialization Stream Protocol.
  11. *
  12. * A String instance is written into an ObjectOutputStream according to
  13. * <a href="{@docRoot}/../platform/serialization/spec/output.html">
  14. * Object Serialization Specification, Section 6.2, "Stream Elements"</a>
  15. */
  16. private static final ObjectStreamField[] serialPersistentFields =
  17. new ObjectStreamField[0];
  18. ···
  19. ···
  20. /**
  21. * Compares this string to the specified object. The result is {@code
  22. * true} if and only if the argument is not {@code null} and is a {@code
  23. * String} object that represents the same sequence of characters as this
  24. * object.
  25. *
  26. * @param anObject
  27. * The object to compare this {@code String} against
  28. *
  29. * @return {@code true} if the given object represents a {@code String}
  30. * equivalent to this string, {@code false} otherwise
  31. *
  32. * @see #compareTo(String)
  33. * @see #equalsIgnoreCase(String)
  34. */
  35. public boolean equals(Object anObject) {
  36. //两个对象的地址是否相同,如果相同则返回true
  37. if (this == anObject) {
  38. return true;
  39. }
  40. //判断anObject对象是否是String类,若不是返回false
  41. if (anObject instanceof String) {
  42. String anotherString = (String)anObject;
  43. //再比较value数组的各个值
  44. int n = value.length;
  45. if (n == anotherString.value.length) {
  46. char v1[] = value;
  47. char v2[] = anotherString.value;
  48. int i = 0;
  49. while (n-- != 0) {
  50. if (v1[i] != v2[i])
  51. return false;
  52. i++;
  53. }
  54. return true;
  55. }
  56. }
  57. return false;
  58. }
  59. }

实际上,自定义的类,其中的equals()方法都是可以我们认为定义的。何为相等,你定义的相等即为相等。就是这么简单。

结语

我尝试着多去看源码,这样子可以学到更多的东西,领略大师写代码都是怎样写的。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注