String的存储方式

Java中内存分析:

栈(Stack):存放基本类型的变量数据和对象的引用。对象不存放在栈中,而是存放在对中(new出来的对象)或者是常量池中(字符串常量对象就存放在常来那个池中)。

堆(heap):存放所有new出来的对象。

常量池(constant pool):在堆中分配出来一块存储区域,存放显示的String常量和基本类型常量(float、int 等)。还存储一些补偿改变的东西。常量池中的数据可以共享。

静态存储:存储静态成员(static定义)。注意,静态只执行一次。

String的存储方式_第1张图片

关于String类的说明

1、String使用private final char value[] 来实现字符串的存储,也就是说String对象创建之后,就不能对此对象中存储的字符串进行修改,就是如此,才说String雷翔是不可变的。

2、String的几种创建方法:

a、直接使用 “” 创建:在编译时就已创建的常量,存放在constant pool。

b、使用new String() 创建:创建的对象存储到heap中,在运行期新创建的。

c、使用new String("someString")创建以及其他的一些重载构造函数创建:

d、使用重载的字符串连接操作符 “aa”+"bb" 创建:创建的也是常量,编译时就确定了,存储到constant pool中。

e、使用重载的字符串连接操作符 “aa”+S1 创建:创建的对象在运行时创建,存储在heap中。

String的存储方式_第2张图片

a:创建字符串时先查看常量池中是否已存在,如果不存在,创建一个并放到常量池,否则就直接将引用只想已存在的字符串。
c:使用new创建一个新对象,不过常量池是否已有值存在,都会将创建的对象放到堆中,再把引用返回给S2。

S1和S3虽然都指向“aa”,但是是不同的对象。

还有几个经常考的面试题:

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

StringBuffer与StringBuilder的区别:

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

你可能感兴趣的:(java,笔记)