面试重点:==和Equals()和Object.Referenceequals()的区别(和Java中的是有区别的)
实例化两个内容一模一样的字符串对象,用三种方式分别判断他们是否是同一个对象
string str1 = new string(new char[] { 'a', 'b', 'c' });
string str2 = new string(new char[] { 'a', 'b', 'c' });
MessageBox.Show((str1 == str2 ? true : false).ToString());//打印true
MessageBox.Show(str1.Equals(str2).ToString());//打印true
MessageBox.Show(object.ReferenceEquals(str1, str2).ToString());//打印false
1.string类型的Equals()方法是继承的Object类被重写的,所以他自己内部的实现并不是去比较堆中两个对象的地址是否一样,而是去比较字符串中的每个字符是否一样,如果一样则返回true,不一样返回false。
2.object.ReferenceEquals()方法比较的是两个对象堆中的地址,可以真正去比较两个变量是否为同一个对象,这种比较方法是比较靠谱的。
3.==双等号这种判断方法,其实string类对操作符双等号也进行了方法封装,但是双等号方法里面还是调用的string类的Equals()方法,也是去比较字符串中的每个字符是否一样,如果一样则返回true,不一样返回false。
4.同样,对于自己写的类,比如Student类,我们也可以重写Object的Equals()方法用来比较Student类对象的方法。
字符串的不可变性
string类是一个密封类(sealed),不可以被其他类继承。
字符串的不可变性:字符串对象一旦被创建就不可能再被改变
string s1 = "abc";
string s2 = "d";
s1 = s1 + s2;//这个赋值过程是在堆中另外开辟了一块空间,并没有修改s1最初的那块内存
MessageBox.Show(s1);
字符串池
通过“abc”这种字符串常量的方式创建字符串变量时,这个字符串会被加入到字符串池中,当在以后还有通过这种方式创建相同的字符串的时候,直接从字符串池中拿出来使用,就不用了再开辟内存空间了。所以此时前后创建的两个字符串变量指向的是同一块堆中的内存。
string s1 = "abc";//当通过这种直接写一个字符串常量的方式创建字符串的时候,除了会为它开辟一块空间外,还会把“abc”这个字符串常量放入到字符串池中。
string s2 = "a";
string s3 = "b";
string s4 = "c";
string s5= new string(new char[] { 'a', 'b', 'c' });//通过new关键字这种方式实例化的字符串对象不会放到字符串池中。
string s6 = s2 + s3 + s4;//这种方式则会重新开辟内存空间,不会从字符串池中取用。
string s7 = "a" + "b" + "c";//这种方式得到的s7和s1这两个变量是指向的堆中的同一块内存,因为这种直接将字符串常量相加后,是在字符串池中取出的地址赋值给了s7变量
由于直接赋值字符串常量创建字符串变量的这种方式会存储到字符串池中,所以当我们在程序中想要存储一个很大的字符串时,一定要从文本中读取,不然这个很大的字符串也会保存到字符串池中,会很浪费内存的。
字符串的常用方法
字符串可通过索引取值,但是不能同过索引进行赋值操作
string s1 = "ajkdksadakd";
for (int i = 0; i < s1.Length; i++)
{
MessageBox.Show(s1[i].ToString());//字符串可通过索引进行读取,但不能写入,因为string类的索引器是只读的。
}
判断一个字符串是否为空字符串的最高效的方法(判断字符串的长度是否为零)
string s = "xsss";
if (s.Length == 0)//判断字符串的长度是否为零是最高效的办法
{
MessageBox.Show("该字符串为空");
}
else
{
MessageBox.Show("该字符串不为空");
}
下面这两种判断字符串是否为空字符串的方法效率比较低
string s = "dsdsds";
if (s == "") { }
if (s == string.Empty) { }
同时判断一个字符串是否为空字符串或者null的方法
string s = "sasasa";
bool b= string.IsNullOrEmpty(s);
MessageBox.Show(b.ToString());
最高效处理字符串的类StringBuilder
使用最原始的字符串累加操作效率会非常低,耗时耗内存
string[] strs = File.ReadAllLines(@"C:\Users\lenovo\documents\visual studio 2015\Projects\DotNET基础加强\05Net基础加强第五天-字符串操作 垃圾回收\txt\1000++++.txt", Encoding.Default);
string s = null;
Stopwatch watch = new Stopwatch();//实例化一个运行时间记录器
watch.Start();
for (int i = 0; i < strs.Length; i++)
{
s += strs[i];//使用最原始的字符串累加操作
}
watch.Stop();
MessageBox.Show(watch.Elapsed.ToString());
使用StringBuilder类进行字符串累加操作效率会非常高
string[] strs = File.ReadAllLines(@"C:\Users\lenovo\documents\visual studio 2015\Projects\DotNET基础加强\05Net基础加强第五天-字符串操作 垃圾回收\txt\1000++++.txt", Encoding.Default);
StringBuilder sb = new StringBuilder();//实例化一个StringBuilder对象
Stopwatch watch = new Stopwatch();//实例化一个运行时间记录器
watch.Start();
for (int i = 0; i < strs.Length; i++)
{
sb.Append(strs[i]);//使用StringBuilder对象进行大量字符串的累加操作
}
watch.Stop();
MessageBox.Show(watch.Elapsed.ToString());
GC垃圾回收器
垃圾回收是CLR的一个核心功能
垃圾回收点的目的:提高内存的利用率
垃圾回收器只回收托管堆中的对象,不回收其他资源,值类型占用的内存是自动释放的
当堆中的对象没有变量来引用它的时候,就表示堆中的这块内存可以被回收了,但是具体什么时候回收这个是无法确定的。
一般在程序中,不需要我们手动去调用GC。