关于String存储机制的理解

一.字符串存储机制

公共语言运行时通过维护一个表来存放字符串,该表称为"暂存池",该容器的key是字符串内容,value是字符串在托管堆上的内存地址.

它包含程序中以编程方式声明或创建的每个唯一的字符串的一个引用。因此,具有特定值的字符串的实例在系统中只有一个。

例如,如果将同一字符串分配给几个变量,运行时就会从暂存池中检索对该字符串的相同引用,并将它分配给各个变量。

 

二.字符串创建解析

情况1.

String s1="hello"; //注意:这里s1赋值字符串常量

s1="world";//注意:这里s1赋值字符串常量


字符串横定性是指一个字符串一经创建,就不可改变。那么也就是说当我们改变s1值的时候,便会在托管堆上重新分配一块新的内存空间("world"),s1便指向这块新的内存空间,而不会影响到原有的内存地址上所存储的值。原有的内存空间("hello"),如果长时间没有其他String变量来指向它,很有可能会被回收或定期清理。

如图所示:

 

 

情况2.

 

string s1="hello"; //注意:这里s1赋值字符串常量

string s2="hello"; //注意:这里s2赋值字符串常量

s1把对象引用复制给了s2,s2指向s1的内存地址。可以说s1和s2是同一个对象,就像

User u2;

User u1=new User();

u2=u1;

如图所示:

 

情况4.

 

string s1="hello"; //注意:这里s1赋值字符串常量

string s2="world"; //注意:这里s2赋值字符串常量

s1和s2各分配新的内存空间,如下图所示:

 

 

 

三.字符串连接

string s1 ="a";和string s2 = "a" + "b";各进行了几次内存分配?

两段代码所分配内存的次数是一样的。在所有的字符串都是字符串常量时,编译器会在编译时将它们连接成一个字符串。也就是说在碰到诸如"a"+"b"这样的代码时,编译器会自动合并为"ab"

但如果是:string s1 = "hello";strings2 = "helloworld";string s3=s1+"world";就不一样了。注意//这里s3是字符串变量s1和常量"world"连接而成的。

测试1

Console.WriteLine(Object.ReferenceEquals(s2,s3)) -------False

原因是s3是动态生成的字符串,这样的字符串是不会添加到暂存池中进行维护到的。具体存储在那里要进一步研究??

 

测试2:

Console.WriteLine(Object.ReferenceEquals(s2,s1)) -------False

s1 和 s2 是两个不同的对象(内存地址不同);


测试3:

s3 = String.Intern(s3);

Console.WriteLine(Object.ReferenceEquals(s2,s3)) -------True

Intern 方法使用暂存池来搜索与 s3 值相等的字符串。 如果存在这样的字符串,则返回暂存池中它的引用。 如果不存在,则向暂存池添加对 s3 的引用,然后返回该引用。

由于存在与s3 具有相同值的字符串s2, 将s2 引用赋给 s3。而 s2 和s3 内存引用是相等,因为它们引用同一字符串。

 

 

这篇文章是否让你对字符串有了更深刻的了解了呢,也许里面还有些不足之处,就算是抛砖引玉了吧害羞,希望大家多多提问和发表意见,洗耳恭听。。。。。吐舌头

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值