==跟equals有什么区别

130 阅读3分钟

对于Object来说

  • 对于 Object 对象来说,equals 和 == 都是一样的,都是比较对象的引用是否相同

对于JDK中其他类来说

  • JDK 中的其他类中通常会重写 equals 以实现具体的值比较,例如 Integer 中的 equalsString 中的 equals 等。

Integer中equals源码实现

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

Integer 中会先将 Integer 对象转换成基础类型 int 值来进行比较,此时就不是比较对象的引用了。

String中equals源码实现


1. equals 方法(实例方法)

public boolean equals(Object anObject) {
    if (this == anObject) {  // 引用相同,值也相同,返回true
        return true;
    }
    return (anObject instanceof String aString)
            && (!COMPACT_STRINGS || this.coder == aString.coder)
            && StringLatin1.equals(value, aString.value);
}

代码逐步解析

  1. this == anObject

    • 首先检查当前对象this是否与传入的对象anObject同一个引用
    • 如果引用相同,则直接返回true,因为同一个引用意味着两者的内容必然相同。
  2. anObject instanceof String aString

    • 检查传入的对象anObject是否是一个String类型。
    • 如果是,则使用 Java 14 引入的 模式匹配(Pattern Matching) 语法,将其转化为变量aString,以便后续操作。
    • 如果anObject不是String类型,则直接返回false(完全不可能相等)。
  3. !COMPACT_STRINGS || this.coder == aString.coder

    • COMPACT_STRINGS 是一个内部标志,指示是否启用了紧凑字符串优化(Compact Strings,Java 9 引入)。
      • Compact Strings:如果字符串只包含 Latin-1 字符,那么它会使用更节省空间的 Latin-1 编码(1 字节表示一个字符)。否则,使用 UTF-16 编码(2 字节表示一个字符)。
    • 如果紧凑字符串优化未启用,直接跳过该检查。
    • 如果启用了紧凑字符串优化,则需要检查两者的coder值是否一致:
      • coder 是一个内部字段,表示字符串的编码(Latin-1 或 UTF-16)。
      • 如果两者的编码不同,则返回false
  4. StringLatin1.equals(value, aString.value)

    • 如果编码一致,调用内部方法StringLatin1.equals对比两个字符串的实际字节数组value
    • value 是字符串对象内部存储的字节数组。
    • 如果字节数组完全相等,则返回true,否则返回false

2. equals 方法(静态方法)

@IntrinsicCandidate
public static boolean equals(byte[] value, byte[] other) {
    if (value.length == other.length) {
        for (int i = 0; i < value.length; i++) {  
            if (value[i] != other[i]) {
                return false;
            }
        }
        return true;
    }
    return false;
}

代码逐步解析

  1. @IntrinsicCandidate 注解

    • 这是一个 JVM 内部优化提示,表示这个方法可能被 JVM 内联优化为高效的机器指令。
    • 它通常不影响代码行为,但可以提升性能。
  2. value.length == other.length

    • 首先检查两个字节数组的长度是否相等。
    • 如果长度不同,则两个字符串显然不可能相等,直接返回false
  3. 字符逐个比较

    • 如果长度相等,则逐个比较两个字节数组中的每个字节。
    • 如果发现有任意一个字节不相等,立即返回false
  4. 全部相等的情况

    • 如果整个循环执行完毕,没有发现不匹配的字节,则说明两个数组完全相等,返回true

String 中的 equals 中可以看出,它也是将 Object 中的引用比较重写成了值比较了

总结

对于 Object 来说,==equals 都是一样的,都是用来对比两个对象的引用是否相同的,而其他 JDK 中的类,如 StringInteger 等,通常都会重写 equals 让其变为比较具体的值是否相同,而非引用是否相同。我们通常会使用 == 来对比两个对象的引用是否相同,使用 equals 对比两个值是否相同(前提是重写了 equals 方法)。