下面是我这两天查了网上的资料得到的一些东西。对于拘留池的作用时间,网上有个说法:进程结束后,字串拘留池中的与此进程所装载的程序集相关的字串常量对象被清除!没有做具体的试验!


string.Intern()

   对于string.Intern(),网上的解释都很好,下面是我载下的一部分(拘留池和字符串池是一个意思):

   intern

   public String intern()

   返回字符串对象的规范化表示形式。 

   一个初始时为空的字符串池,它由类 String 私有地维护。 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。    它遵循对于任何两个字符串 s 和 t,当且仅当 s.equals(t) 为 true 时,s.intern() == t.intern() 才为 true

   就是说,拘留池中存在,则直接返回拘留池中的地址,否则先在拘留池中新建一个对象,再返回相应的地址。

 string.IsInterned,,检查字符串是否已经位于拘留池中


我对string拘留池主要做下面几个验证:


运行下面语句           

            string str = "ab";

            string str1 = "a" + "b";

            string strIntern1 = string.IsInterned(str);     //ab

            string strIntern2 = string.IsInterned(str1);   //ab

            bool bl = object.ReferenceEquals(str, str1);  //true

如上,可证明直接给变量赋字符串常量和赋相加字符串常量都会到拘留池中新建对象,不会在堆中新建对象。


运行下面语句

            string str0 = "ab";

            string str1 = str0 + "c";

            string strIntern2 = string.IsInterned(str1);   //null

说明拘留池中没有创建新的对象。加上下面代码,因为直接赋常量字符串必然会在拘留池中,所以验证他们地址不相等也可以证明。

            string str = "abc";

            bool bl = object.ReferenceEquals(str, str1);//false

由上可得,做+运算的时候,如果参数有变量,会在堆中创建新对象,不会在拘留池中新建对象。


            string strnew = new string(new char[] {'a','b','c','d' });

            string strIntern1 = string.IsInterned(strnew);//null

说明拘留池中没有创建新的对象。加上下面代码。

            string str = "abcd";

            bool bl = object.ReferenceEquals(str, strnew);//false

可以得出,new也只是在堆中创建了新的对象,但是不会在拘留池中新建对象。


对于format,copy,concat,join,都不会在拘留池中新建对象的,看下面的例子:

Format:

            string strformat= string.Format("{0:D}",DateTime.Today)

            string.IsInterned(strformat);//null

Copy:

            string scopypre = "abc";

            scopypre += "def";

            string scopypost = string.Copy(scopypre);

            string str = string.IsInterned(scopypost);

            bool bl = object.ReferenceEquals(scopypre, scopypost);

Concat:

           string strconcat = string.Concat(7924123 );

           string strconcatp = string.IsInterned(strconcat);

Join:

            string strjoin = string.Join(".",new string[]{"a","b"} );

            string strjoinp = string.IsInterned(strjoin);

返回值都为null.



现在还有个问题,如果两个字符串都是在堆里面新建的对象,两者值又等,他们会指向堆中的同一个地址吗?答案是不会。

看例子:

            string g0 = "abcdef";

            g0 += "hijk";

            string g1 = new string(new char[] { 'a', 'b', 'c', 'd', 'e', 'f', 'h', 'i', 'j', 'k' });

            object.ReferenceEquals(g0, g1);//false