本文目录一览:
1、Java中String,StringBuffer和StringBuilder的区别和堆栈内存分配
2、JAVA里String数组在内存分配中分配的空间每个占几个字节?
3、Java中 String字符串内存分配问题
4、Java StringBuilder和String的内存分析的问题
Java中String,StringBuffer和StringBuilder的区别和堆栈内存分配
- 三者在执行速度方面的比较:
StringBuilder > StringBuffer > String
- String(StringBuffer,StringBuilder)的原因
String
:字符串常量StringBuffer
:字符串变量StringBuilder
:字符串变量
从上面的名字可以看到,String
是“字符串常量”,也就是不可改变的对象。例如:
String s = "abcd";
s = s + 1;
System.out.print(s); // result: abcd1
我们看似改变了String
类型的变量s
,但实际上并没有改变原来的对象。JVM解析这段代码时,首先创建对象s
,赋予"abcd"
,然后创建一个新的对象用于执行第二行代码。原来的对象s
并没有变化,因此说String
类型是不可改变的对象。这种机制导致每次操作字符串时都在不断创建新对象,效率较低。
而StringBuffer
与StringBuilder
是字符串变量,是可改变的对象。每次对字符串操作时,实际上是在一个对象上进行操作,不会创建额外的对象,因此速度更快。
3. 一个特殊的例子
String str = "This is only a" + " simple" + " test";
StringBuffer builder = new StringBuilder("This is only a").append(" simple").append(" test");
生成str
对象的速度非常快,因为JVM优化了字符串拼接:
String str = "This is only a simple test";
但如果字符串来自其他String
对象,速度就没那么快了:
String str2 = "This is only a";
String str3 = " simple";
String str4 = " test";
String str1 = str2 + str3 + str4;
这时JVM会按照原来的方式处理。 4. StringBuilder与StringBuffer
StringBuilder
:线程非安全的StringBuffer
:线程安全的
当字符串缓冲区被多个线程使用时,JVM不能保证StringBuilder
的操作是安全的,虽然它的速度最快。但可以保证StringBuffer
能正确操作。大多数情况下是在单线程下进行操作,所以建议使用StringBuilder
。
使用总结:
- 如果要操作少量的数据,使用
String
- 单线程操作字符串缓冲区并处理大量数据,使用
StringBuilder
- 多线程操作字符串缓冲区并处理大量数据,使用
StringBuffer
JAVA里String数组在内存分配中分配的空间每个占几个字节?
Java中一个int
占4个字节,由于Java是Unicode编码,一个char
可以占2个字节,可以存储一个汉字。一个String
,要看有几个字母或者几个汉字,一个英文字母占1个字节,一个汉字占2个字节,以此类推计算。
Java中 String字符串内存分配问题
JVM中有个String pool
,一般在池中有的对象就不会再去生成一个新的。
String s1 = "abc";
生成了一个字符串对象"abc"
并放入pool
中,定义了一个String
变量s1
并指向"abc"
。
String s = "abc" + s1 + "def";
等式右边有三个String
对象:"abc"
、s1
、"def"
。
这里"abc" == s1
是true
,说明引用的是同一个内存地址。
"abc"
已经在池中了,直接从池中取出,这句又创建了一个"def"
的String
对象并放入池中。
当两个String
对象做连接时,又会创建一个新的String
对象"abcabc"
,并放入池中;然后再做字符串相加"abcabc" + "def"
又生成一个字符串对象,最后变量s
指向这个新的String
对象。
所以用+
来连接字符串会产生很多临时字符串对象,效率低。一般使用StringBuffer
或StringBuilder
来做字符串连接。
可以使用new String()
来生成一个新的String
对象并单独分配内存空间。
查了下资料,已经改了回答内容。
String s = "abc";
这句是定义一个String
变量s
,JVM会先去字符串池中查找有没有"abc"
,有的话就把s
指向"abc"
,没有就会先在池中创建一个,再让s
指向"abc"
。
String s = new String("abc");
这句是先定义一个String
变量s
,然后在内存中分配新的空间"abc"
,再让s
指向这个内存地址。
Java StringBuilder和String的内存分析的问题
它们的实现机制不同,这个和有没有人接收没有关系。concat()
返回的是一个指向常量池"abc"
的全新对象,没有改变s2
的引用。至于replace()
方法也有多种实现方式,但据我猜测它的实现就像C中的动态数组一样。总之不管它是怎么实现的,sb2
最终就是指向了"aaaccc"
。
再多说一句,这个应该在逻辑上理解,而底层实现多种多样,怎么实现都不可以,无非就是一个效率问题。concat
方法意在返回一个连接之后的数组,而非销毁对象s2
。append
方法是附加的意思,意义不言自明。