System.String的内存管理机制是怎样的?

2026-05-25 09:423阅读0评论SEO问题
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计738个文字,预计阅读时间需要3分钟。

System.String的内存管理机制是怎样的?

在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:nop
IL_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)

publicstaticstringConcat(stringstr0,stringstr1)
{
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;
}

通过比较:

System.String的内存管理机制是怎样的?

string是每次拼接后都需要分配空间,并返回新string的引用。而StringBulder则是预分配空间,而当字符串拼接时,则先检查字符串的空间,再决定是否需要分配新空间。向堆上申请内存空间是比较耗时的操作。

本文共计738个文字,预计阅读时间需要3分钟。

System.String的内存管理机制是怎样的?

在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:nop
IL_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)

publicstaticstringConcat(stringstr0,stringstr1)
{
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;
}

通过比较:

System.String的内存管理机制是怎样的?

string是每次拼接后都需要分配空间,并返回新string的引用。而StringBulder则是预分配空间,而当字符串拼接时,则先检查字符串的空间,再决定是否需要分配新空间。向堆上申请内存空间是比较耗时的操作。