String、StringBuffer和StringBuilder间的关系

String是用final关键词修饰的不可变类。

final修饰的字段创建以后就不可改变。final类表示该类不可被继承,方法不能被重写,且由于其方法为final的,编译时可能将其以inline方式完成编译,此举能够使性能平均提高50%。变量不能被重新赋值。即每次对一个String类实体进行修改都需要重新分配地址并把原来String对象的引用指向该地址。

String重写了hashCode和equals方法。实现了Serializable和Comparable接口。

重写hashCode和equals方法一方面是因为String类实体可能存放到java容器中。hashCode用于hash算法获取其需要存储的位置,这就要求相同的String其hashCode是相同的。而equals用于对比String字符串是否相等。

另一方面,equals是Object类的方法,其底层是靠 == 实现的,即默认比较的是变量地址。而如果采用new String()的方式新建变量则其地址一定不同。所以equals方法对比的是其具体的字符串是否相等而非仅仅比较其地址。

缺点:

会在内存中产生大量碎片,且效率低下(其效率比StringBuffer、StringBuilder都低)。

优点:

final修饰的String类使其能够保证线程安全。

String为什么要设计为final类呢?

设计为final就是为了不想改变,理由有两点,设计(安全)和效率。

因为字符串是不可变的,所以在它创建的时候hashcode就被缓存了,不需要重新计算,这就使得字符串很适合作为Map中的键,字符串的处理速度要快过其它的键对象。这也是为什么HashMap中的键往往都使用字符串。

为什么String被设计为final

StringBuffer是线程安全的。

线程安全是因为其在大多数方法中都使用的synchronized关键字。这样做虽然做到了安全,但是损失了效率。其效率介于String和StringBuilder之间。

StringBuilder是线程非安全的。

StringBuffer和StringBuilder有很多类似的部分。它们的空参构造函数采用了默认长度为16的字符数组。或者开发人员可指定其初始长度与初始内容(指定初始内容时其会在内存中开辟一个字符串长+16的字符数组)。此外,它们的toString方法都返回了一个新的字符串而非内部存储的char数组(StringBuffer在修改时会显示将toString中字符串置空)。

你可能感兴趣的:(String、StringBuffer和StringBuilder间的关系)