String s1 = "i love spark";

        String s2 =  new String("i love spark");

        System.out.println(s1.hashCode()); // 450829510
        System.out.println(s2.hashCode()); // 450829510

        System.out.println(s1 == s2);       // false   判断地址是否相等
        System.out.println(s1.equals(s2)); // true 
        System.out.println(s1.hashCode() == s2.hashCode()); // true 

两种初始化的方式有什么区别?

String s1 = "i love spark";
是以字面量的定义方式, i love spark 存储在字符串常量池

String常量池

String s1 = new String("i love spark");
造了几个对象?
两个。

一个是new 在堆的对象, 另一个是常量池中的字面量对象。

String s2 = new String("a") + new String("b")

对象1: new StringBuilder()
对象2: new String("a") 堆区的对象
对象3: 常量区中的 "a"
对象4: new String("b") 堆区的对象
对象5: 常量区中的 "b"
对象6: StringBuilder的 toString() 方法也会 new String("ab")

String JDK 1.8 之后的变化

String 与 char[] 的关系, 持续到JDK1.8 。在JDK1.9 之后, 不再使用char[] 存储数据,而是使用 byte[] 存储, 出于压缩堆空间的考量 —— 修改原因参见于 JEP254



 > Motivation
The current implementation of the String class stores characters in a char array, using two bytes (sixteen bits) for each character. Data gathered from many different applications indicates that strings are a major component of heap usage and, moreover, that most String objects contain only Latin-1 characters. Such characters require only one byte of storage, hence half of the space in the internal char arrays of such String objects is going unused.

Description
We propose to change the internal representation of the String class from a UTF-16 char array to a byte array plus an encoding-flag field. The new String class will store characters encoded either as ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes per character), based upon the contents of the string. The encoding flag will indicate which encoding is used.

String-related classes such as AbstractStringBuilder, StringBuilder, and StringBuffer will be updated to use the same representation, as will the HotSpot VM's intrinsic string operations.

This is purely an implementation change, with no changes to existing public interfaces. There are no plans to add any new public APIs or other interfaces.

The prototyping work done to date confirms the expected reduction in memory footprint, substantial reductions of GC activity, and minor performance regressions in some corner cases.

不可变性

StringBuffer与StringBuilder

JDK1.9 也相应兼容了String的变化。

这2个兄弟怎么使用? 有什么区别?

StackOverflow 中, 我只记住了这样的一个答案 _
StringBuffer是线程同步的, 而StringBuilder不是.

(我是这么记的, buffer 中间两个ff 是相同的字母 - 线程同步).