String 类型之间的比较

最近有同学面试,遇到些老生常谈的问题,突然问起一些关于 String 的数据结构和对象之间值的比较,发现还挺有意思,稍不注意就有可能答错,可能你平时可能很少去关注这些细节,这里记录一下。

@Test
public void contextLoads() {
    String a = "abc";
    String b = "de";
    String c = new String("abc");
    String d = new String("de");
    String e = "abcde";
    String f = "abc" + "de";

    final String g = "de";

    String h = a + b;
    String i = a + d;
    String j = a + g;
    String k = "abc" + g;
    String l = "abc" + new String("de");

    //a变量 地址在常量池,c 是引用地址在堆区,所以不相等。
    System.out.println(a==c); //false
    //比较的是值是否相等
    System.out.println(a.equals(c)); //true
    //编译时期,a变量 与 b变量 的和,实际上调用的是 StringBuilder 的 append 方法,再 toString()。
    System.out.println(h==e); //false
    //编译时期,a变量 与 d变量 的和,实际上调用的是 StringBuilder 的 append 方法,再 toString()。
    System.out.println(i==e); //false
    //编译时期,就能确定 f变量 的值,"abc" 和 "de" 是常量,编译器会拼接成 "abcde"。
    System.out.println(f==e); //true
    //编译时期,a变量 与 常量g 的和,实际上调用的是 StringBuilder 的 append 方法,再 toString()。
    System.out.println(j==e); //false
    //编译时期,"abc"常量 与 final 修饰的 常量g 的和,实际上 "abc" + "de" 的和。
    System.out.println(k==e); //true
    //编译时期,"abc"常量 与 new String(""de) 匿名对象的和,实际上调用的是 StringBuilder 的 append 方法,再 toString()。
    System.out.println(l==e); //false
}

这里要要区分常量和变量,虽然 String 是不可变的常量,但是在这里,声明的 a 字面量是个变量,因为 a 在栈区,值 “abc” 是常量,在常量池,a 是 “abc” 的引用,而 b 也在栈区,但是 new String(“de”) 在堆区,而 “de” 在常量池。


当 final 变量是基本数据类型以及 String 类型时,如果在编译期间就能知道它的确切值,则编译器会把它当作编译器常量使用,也就是说在用到该 final 变量的地方,相当于直接访问的这个常量,不需要运行时确定。因此在上面的一段代码中,由于 变量g 被 final 修饰,因此会被当作编译器常量,所以在使用到 g 的地方会直接将 变量b 替换为它的值。

未经允许不得转载:极客萌动 » String 类型之间的比较

赞 (1)

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址