Skip to content

String 中的 equals 是如何重写的

cxuan edited this page Jun 15, 2020 · 1 revision

String 代表的是 Java 中的字符串,String 类比较特殊,它整个类都是被 final 修饰的,也就是说,String 不能被任何类继承,任何 修改 String 字符串的方法都是创建了一个新的字符串。

equals 方法是 Object 类定义的方法,Object 是所有类的父类,当然也包括 String,String 重写了 equals 方法,下面我们来看看是怎么重写的

  • 首先会判断要比较的两个字符串它们的引用是否相等。如果引用相等的话,直接返回 true ,不相等的话继续下面的判断
  • 然后再判断被比较的对象是否是 String 的实例,如果不是的话直接返回 false,如果是的话,再比较两个字符串的长度是否相等,如果长度不想等的话也就没有比较的必要了;长度如果相同,会比较字符串中的每个 字符 是否相等,一旦有一个字符不相等,就会直接返回 false。

下面是它的流程图

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

if (this == anObject) {
  return true;
}

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

在 JDK1.7 及以后调用 intern 方法是判断运行时常量池中是否有指定的字符串,如果没有的话,就把字符串添加到常量池中,并返回常量池中的对象。

验证过程如下

private void StringOverrideEquals(){

  String s1 = "aaa";
  String s2 = "aa" + new String("a");
  String s3 = new String("aaa");

  System.out.println(s1.intern().equals(s1));
  System.out.println(s1.intern().equals(s2));
  System.out.println(s3.intern().equals(s1));

}
  • 首先 s1.intern.equals(s1) 这个无论如何都返回 true,因为 s1 字符串创建出来就已经在常量池中存在了。

  • 然后第二条语句返回 false,因为 s1 返回的是常量池中的对象,而 s2 返回的是堆中的对象

  • 第三条语句 s3.intern.equals(s1),返回 true ,因为 s3 对象虽然在堆中创建了一个对象,但是 s3 中的 "aaa" 返回的是常量池中的对象。

Clone this wiki locally