System.String的内存管理机制是怎样的?
- 内容介绍
- 文章标签
- 相关推荐
本文共计738个文字,预计阅读时间需要3分钟。
在Java中,`String` 类型是不可变的,这意味着一旦创建了 `String` 对象,它的值就不能被改变。如果你尝试修改 `String` 对象的值,将会导致编译错误。
以下是一个错误的代码示例,它试图修改一个 `String` 对象:
javastring s=hello;s[0]='a';
这段代码会导致以下错误:
Error3Property or indexer 'string.this[int]' cannot be assigned to -- it is read only
实际上,你可以通过以下方式来修改一个 `String`:
javastring s=hello;String newS=s.replace('h', 'a');
这里,我们创建了一个新的 `String` 对象 `newS`,它包含了修改后的内容,而不是直接修改原始的 `String` 对象 `s`。
1.String分配了之后就无法更改?
下面的代码会造成编译错误:
strings="hello";s[0]='a';
会造成:
Error3Property or indexer 'string.this[int]' cannot be assigned to -- it is read only
事实上是可以改变的:
unsafe{
strings="hello";
fixed(char*p1=s)
{
*p1='a';
}
}
2.String不能用new来构造?
由于代码
strings=newstring("hello");会报错,没有此类ctor但是实际上string有8个ctor:
publicString(char*value);publicString(char[]value);
publicString(sbyte*value);
publicString(charc,intcount);
publicString(char*value,intstartIndex,intlength);
publicString(char[]value,intstartIndex,intlength);
publicString(sbyte*value,intstartIndex,intlength);
publicString(sbyte*value,intstartIndex,intlength,Encodingenc);
3.字符串“+”会生成新的字符串?
strings="he"+"ll"+"o";看看IL:
IL_0000:nopIL_0001:ldstr"hello"
IL_0006:stloc.0
IL_0007:ret
事实上是一个字符串,编译器做了我们不知道的事情。
4.StringBuilder为什么会比String性能好?
Strings=null;for(inti=0;i<100;i++)
s+=i.ToString();
+实际调用的是String的静态方法public static string Concat(string str0, string str1)
{
if(IsNullOrEmpty(str0))
{
if(IsNullOrEmpty(str1))
{
returnEmpty;
}
returnstr1;
}
if(IsNullOrEmpty(str1))
{
returnstr0;
}
intlength=str0.Length;
stringdest=FastAllocateString(length+str1.Length);
FillStringChecked(dest,0,str0);
FillStringChecked(dest,length,str1);
returndest;
}
下面的代码:
StringBuildersb=newStringBuilder();for(inti=0;i<100;i++)
sb.Append(i.ToString());
Append(String)方法:
publicStringBuilderAppend(stringvalue){
if(value!=null)
{
stringstringValue=this.m_StringValue;
IntPtrcurrentThread=Thread.InternalGetCurrentThread();
if(this.m_currentThread!=currentThread)
{
stringValue=string.GetStringForStringBuilder(stringValue,stringValue.Capacity);
}
intlength=stringValue.Length;
intrequiredLength=length+value.Length;
if(this.NeedsAllocation(stringValue,requiredLength))
{
stringnewString=this.GetNewString(stringValue,requiredLength);
newString.AppendInPlace(value,length);
this.ReplaceString(currentThread,newString);
}
else
{
stringValue.AppendInPlace(value,length);
this.ReplaceString(currentThread,stringValue);
}
}
returnthis;
}
通过比较:
string是每次拼接后都需要分配空间,并返回新string的引用。而StringBulder则是预分配空间,而当字符串拼接时,则先检查字符串的空间,再决定是否需要分配新空间。向堆上申请内存空间是比较耗时的操作。
本文共计738个文字,预计阅读时间需要3分钟。
在Java中,`String` 类型是不可变的,这意味着一旦创建了 `String` 对象,它的值就不能被改变。如果你尝试修改 `String` 对象的值,将会导致编译错误。
以下是一个错误的代码示例,它试图修改一个 `String` 对象:
javastring s=hello;s[0]='a';
这段代码会导致以下错误:
Error3Property or indexer 'string.this[int]' cannot be assigned to -- it is read only
实际上,你可以通过以下方式来修改一个 `String`:
javastring s=hello;String newS=s.replace('h', 'a');
这里,我们创建了一个新的 `String` 对象 `newS`,它包含了修改后的内容,而不是直接修改原始的 `String` 对象 `s`。
1.String分配了之后就无法更改?
下面的代码会造成编译错误:
strings="hello";s[0]='a';
会造成:
Error3Property or indexer 'string.this[int]' cannot be assigned to -- it is read only
事实上是可以改变的:
unsafe{
strings="hello";
fixed(char*p1=s)
{
*p1='a';
}
}
2.String不能用new来构造?
由于代码
strings=newstring("hello");会报错,没有此类ctor但是实际上string有8个ctor:
publicString(char*value);publicString(char[]value);
publicString(sbyte*value);
publicString(charc,intcount);
publicString(char*value,intstartIndex,intlength);
publicString(char[]value,intstartIndex,intlength);
publicString(sbyte*value,intstartIndex,intlength);
publicString(sbyte*value,intstartIndex,intlength,Encodingenc);
3.字符串“+”会生成新的字符串?
strings="he"+"ll"+"o";看看IL:
IL_0000:nopIL_0001:ldstr"hello"
IL_0006:stloc.0
IL_0007:ret
事实上是一个字符串,编译器做了我们不知道的事情。
4.StringBuilder为什么会比String性能好?
Strings=null;for(inti=0;i<100;i++)
s+=i.ToString();
+实际调用的是String的静态方法public static string Concat(string str0, string str1)
{
if(IsNullOrEmpty(str0))
{
if(IsNullOrEmpty(str1))
{
returnEmpty;
}
returnstr1;
}
if(IsNullOrEmpty(str1))
{
returnstr0;
}
intlength=str0.Length;
stringdest=FastAllocateString(length+str1.Length);
FillStringChecked(dest,0,str0);
FillStringChecked(dest,length,str1);
returndest;
}
下面的代码:
StringBuildersb=newStringBuilder();for(inti=0;i<100;i++)
sb.Append(i.ToString());
Append(String)方法:
publicStringBuilderAppend(stringvalue){
if(value!=null)
{
stringstringValue=this.m_StringValue;
IntPtrcurrentThread=Thread.InternalGetCurrentThread();
if(this.m_currentThread!=currentThread)
{
stringValue=string.GetStringForStringBuilder(stringValue,stringValue.Capacity);
}
intlength=stringValue.Length;
intrequiredLength=length+value.Length;
if(this.NeedsAllocation(stringValue,requiredLength))
{
stringnewString=this.GetNewString(stringValue,requiredLength);
newString.AppendInPlace(value,length);
this.ReplaceString(currentThread,newString);
}
else
{
stringValue.AppendInPlace(value,length);
this.ReplaceString(currentThread,stringValue);
}
}
returnthis;
}
通过比较:
string是每次拼接后都需要分配空间,并返回新string的引用。而StringBulder则是预分配空间,而当字符串拼接时,则先检查字符串的空间,再决定是否需要分配新空间。向堆上申请内存空间是比较耗时的操作。

