java记录-String的基础知识

1.String 类是不可改变的,所以你一旦创建了 String 对象,那它的值就无法改变了,因为String使用private final char value[]来实现字符串的存储。

2.String是一个对象,不是基本的数据类型,char[]和所有的对象一样存放在堆内存中,而基本数据类型是保存在栈中的。

3.Java中的内存分析:

  • 栈(stack):存放基本数据类型的变量数据和对象的引用。对象不放在栈中,而是存放在堆中(new出来的对象)。字符串常量对象放在常量池中。
  • 堆(heap):存放所有new出来的对象。
  • 常量池(constant pool):在堆中分配出来的一块存储区域,存放显示的String常量和基本类型常量(float,int等),常量池中的数据可以共享。
  • 静态存储:存储静态成员(static定义),静态只能执行一次。

java记录-String的基础知识

4.String的几种创建方式:

  • 直接使用“”创建,在编译时就已经创建的常量,存放在constant pool中。
  • 使用new String()创建,创建的对象存储到heap中,在运行期间新创建的。
  • 使用new String(“哈哈”)创建以及其他的重载构造函数创建。
  • 使用重载的字符串连接操作符 “aa”+"bb" 创建:创建的也是常量,编译时就确定了,存储到constant pool中。 
  • 使用重载的字符串连接操作符 “aa”+S1 创建:创建的对象在运行时创建,存储在heap中。

5.创建字符串的时候先查询常量池中是否已经存在,如果不存在,创建一个放入常量池中,否则就直接将引用指向已存在的字符串。

6.使用new创建一个新对象,不管常量池中是否已经存在,都会讲创建的对象放入堆中,再把引用返回S3,S1和S3虽然都指向“aa”,但是是不同的对象。

java记录-String的基础知识

7.还有几个经常考的面试题:
1.
String s1 = new String("s1") ;
String s2 = new String("s1") ;
上面创建了几个String对象?
答案:3个 ,编译期Constant Pool中创建1个,运行期heap中创建2个.

2.

String s1 = "s1";
String s2 = s1;
s2 = "s2";
s1指向的对象中的字符串是什么?
答案: "s1"
综上:
String str1 = "a";//constant pool
String str2 = "b";//constant pool
String str3 = new String("a");//heap
System.out.println(str1 == str3);//false
String str4 = "a"+str2;//heap
String str5 = "a"+"b";//constant pool
String str6 = new String("ab");//heap
String str7 = "ab";//constant pool
System.out.println(str4 == str5);//false
System.out.println(str4.intern() == str5);//true
System.out.println(str4 == str6);//false
System.out.println(str5 == str7);//true
String str8 = str6;//heap
System.out.println(str6 == str8);//true
String str9 = new String("ab");//heap
System.out.println(str6 == str9);//false

8.StringBuilder和StringBuffer的区别

jdk的实现中StringBuffer与StringBuilder都继承自AbstractStringBuilder,对于多线程的安全与非安全看到StringBuffer中方法前面的一堆synchronized就大概了解了。

这里随便讲讲AbstractStringBuilder的实现原理:我们知道使用StringBuffer等无非就是为了提高java中字符串连接的效率,因为直接使用+进行字符串连接的话,jvm会创建多个String对象,因此造成一定的开销。AbstractStringBuilder中采用一个char数组来保存需要append的字符串,char数组有一个初始大小,当append的字符串长度超过当前char数组容量时,则对char数组进行动态扩展,也即重新申请一段更大的内存空间,然后将当前char数组拷贝到新的位置,因为重新分配内存并拷贝的开销比较大,所以每次重新申请内存空间都是采用申请大于当前需要的内存空间的方式,这里是2倍