【笔记】String、StringBuilder 和 StringBuffer 详解

  • 来源

  • String 类其实是通过 char 数组来保存字符串的。

  • String 对象是由final 修饰的,一旦使用 final 修饰的类不能被继承、方法不能被重写、属性不能被修改。而且 String 不只只有类是 final 的,它其中的方法也是由 final 修饰的,换句话说,Sring 类就是一个典型的 Immutable 类。

  • 下面分别存在(创建)了几个对象?

String s1 = "aaa";  // 1个
String s2 = "bbb" + "ccc";  // 1个 (编译器做了优化)
String s3 = s1 + "bbb"; // 3个 (创建一个 StringBuilder 对象然后执行初始化。执行 + 号相当于是执行 new StringBuilder.append() 操作,并自动执行 toString() 方法。)
String s4 = new String("aaa");  // 2个
  • String 对象底层是使用了 StringBuilder 对象的 append 方法进行字符串拼接的

  • StringBuffer 对象 代表一个可变的字符串序列,当一个 StringBuffer 被创建以后,通过 StringBuffer 的一系列方法可以实现字符串的拼接、截取等操作。一旦通过 StringBuffer 生成了最终想要的字符串后,就可以调用其 toString 方法来生成一个新的字符串。

  • StringBuffer 是线程安全的,在字符串拼接上面直接使用 synchronized 关键字加锁,从而保证了线程安全性。 StringBuilder 其实是和 StringBuffer 几乎一样,只不过 StringBuilder 是非线程安全的。

  • String 在 JDK1.6 之后提供了 intern() 方法,intern 方法是一个 native 方法,它底层由 C/C++ 实现,intern 方法的目的就是为了把字符串缓存起来,在 JDK1.6 中却不推荐使用 intern 方法,因为 JDK1.6 把方法区放到了永久代(Java 堆的一部分),永久代的空间是有限的,除了 Fullgc 外,其他收集并不会释放永久代的存储空间。JDK1.7 将字符串常量池移到了堆内存 中。

  • 在 JDK 1.6 及之前的版本中,常量池是分配在方法区中永久代(Parmanent Generation)内的,而永久代和 Java 堆是两个完全分开的区域。 从JDK 1.7开始去永久代,字符串常量池已经被转移至 Java 堆中,开发人员也对 intern 方法做了一些修改。因为字符串常量池和 new 的对象都存于 Java 堆中,为了优化性能和减少内存开销,当调用 intern 方法时,如果常量池中已经存在该字符串,则返回池中字符串;否则直接存储堆中的引用,也就是字符串常量池中存储的是指向堆里的对象。

public static void main(String[] args) {
  String a = new String("ab");
  String b = new String("ab");
  String c = "ab";
  String d = "a";
  String e = new String("b");
  String f = d + e;
  System.out.println(a.intern() == b);  // false
  System.out.println(a.intern() == b.intern()); // true
  System.out.println(a.intern() == c);  // true
  System.out.println(a.intern() == f);  // false
}
  • StringBuilder 的初始容量是 16,当然也可以指定 StringBuilder 的初始容量。扩容后的字符串长度会是原字符串长度增加一倍 + 2,如果扩容后的长度还比拼接后的字符串长度小的话,那就直接扩容到它需要的长度 newCapacity = minCapacity,然后再进行数组的拷贝。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。