05Net基础加强第五天-字符串操作 垃圾回收

本文详细解析C#中字符串对象的比较方法,包括==、Equals()和ReferenceEquals()的区别,探讨字符串的不可变性、字符串池的概念及StringBuilder类在高效处理字符串中的应用,同时介绍GC垃圾回收机制。

面试重点:==和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。

基础-0-Java虚拟机导学课程 11:33 基础-1-初识JVM 22:27 基础-2-Java虚拟机的组成 04:47 基础-3-字节码文件的组成-以正确的姿势打开字节码文件 10:41 基础篇(补)-3.5-字节码文件的组成-基础信息 15:54 基础-4-字节码文件的组成-常量池和方法 25:51 基础-5-字节码文件常见工具的使用1 11:43 基础-6-字节码文件常见工具的使用2 22:20 基础-7-类的生命周期加载阶段 22:09 基础-8-类的生命周期2连接阶段 19:58 基础-9-类的生命周期3初始化阶段 26:27 基础-10-类加载器的分类 13:56 基础-11-启动类加载器 13:36 基础-12-扩展和应用程序类加载器 16:26 基础-13-双亲委派机制 18:43 基础-14-打破类的双亲委派机制-自定义类加载器 25:16 基础-15-打破双亲委派机制2-线程上下文类加载器 20:17 基础-16-打破双亲委派机制3-osgi和类的热部署 11:53 基础-17-JDK9之后的类加载器 09:05 基础-18-运行时数据区-程序计数器 15:42 基础-19--局部变量表 19:20 基础-20--操作数栈和帧数据 12:08 基础-21--内存溢出 15:28 基础-22-堆内存 25:56 基础-23-方法区的实现 16:25 基础-24-方法区-字符串常量池 20:40 基础-25-直接内存 12:39 基础-26-自动垃圾回收 11:32 基础-27-方法区的回收 11:32 基础-28-引用计数法 15:41 基础-29-可达性分析法 20:25 基础-30-软引用 24:40 基础-31-弱虚终结器引用 12:08 基础-32-垃圾回收算法的评价标准 13:31 基础-33-垃圾回收算法1 10:05 基础-34-垃圾回收算法-分代GC 20:19 基础-35-垃圾回收器1 15:54 基础-36-垃圾回收器2 11:44 基础-37-垃圾回收器3 15:51 基础-38-g1垃圾回收器 26:23 实战篇-1-内存泄漏和内存溢出 21:25 实战篇-2-解决内存泄漏-监控-top命令 12:16 实战篇-3-解决内存泄漏-监控-visualvm 12:50 实战篇-4-解决内存泄漏-监控-arthas tunnel 15:18 实战篇-5-解决内存泄漏-监控-prometheus-grafana 17:53 实战篇-6-解决内存泄漏-堆内存状况对比 08:39 实战篇-7-解决内存泄漏-内存泄漏产生的几大原因 16:01 实战篇-8-内存泄漏产生的原因2 13:30 实战篇-9-内存泄漏产生的原因3 10:43 实战篇-10-内存泄漏产生的原因4 10:04 实战篇-11-内存泄漏产生原因2-并发请求问题 17:30 实战篇-12-导出堆内存快照并使用MAT分析 08:38 实战篇-13-MAT内存泄漏检测原理 17:23 实战篇-14-服务器导出内存快照和MAT使用小技巧 13:31 实战篇-15-实战1-查询大数据量导致的内存溢出 26:24 实战篇-16-实战2-mybatis导致的内存溢出 10:34 实战篇-17-实战3-k8s容器环境导出大文件内存溢出 26:13 实战篇-18-系统不处理业务时也占用大量的内存 14:13 实战篇-19-文章审核接口的内存问题 18:28 实战篇-20-btrace和arthas在线定位问题 20:15 实战篇-21-GC调优的核心目标 11:23 实战篇-22-GC调优的常用工具 12:05 实战篇-23-GC调优的常见工具2 14:25 实战篇-24-常见的GC模式 13:38 实战篇-25-基础JVM参数的设置 28:31 实战篇-26-垃圾回收器的选择 18:04 实战篇-27-垃圾回收参数调优 07:56 实战篇-28-实战-GC调优和内存调优 30:43 实战篇-29-性能问题的现象和解决思路 10:49 实战篇-30-定位进程CPU占用率高的问题 18:52 实战篇-31-接口响应时间很长问题的定位 14:44 实战篇-32-火焰图定位接口响应时间长的问题 12:03 实战篇-33-死锁问题的检测 14:37 实战篇-34-基准测试框架JMH的使用 28:24 实战篇-35-实战-性能调优 26:36 高级篇-01-GraalVM介绍 12:13 高级篇-02-GraalVM的两种运行模式 15:43 高级篇-03-使用SpringBoot3构建GraalVM应用 15:08 高级篇-04-将GraalVM应用部署到函数计算 25:13 高级篇-05-将GraalVM应用部署到Serverless 09:14 高级篇-06-参数优化和故障诊断 22:31 高级篇-07-垃圾回收器的技术演进 13:09 高级篇-08-ShenandoahGC 22:50 高级篇-09-ZGC 14:35 高级篇-10-实战案例-内存不足时的垃圾回收测试 09:47 高级篇-11-JavaAgent技术 12:16 高级篇-12-JavaAgent环境搭建 15:24 高级篇-13-查看内存的使用情况 18:48 高级篇-14-生成内存快照 13:47 高级篇-15-获取类加载器的信息 16:26 高级篇-16-打印类的源码 18:00 高级篇-17-使用ASM增强方法 29:45 高级篇-18-使用ByteBuddy打印方法执行的参数和耗时 21:55 高级篇-19-APM系统和数据采集 24:30 原理篇-01-栈上的数据存储 15:05 原理篇-02-boolean在栈上的存储方式 22:48 原理篇-03-对象在堆上的存储1 17:27 原理篇-04-对象在堆上的存储2 25:14 原理篇-05-方法调用的原理1-静态绑定 19:26 原理篇-06-方法调用的原理2-动态绑定 15:25 原理篇-07-异常捕获的原理 12:00 原理篇-08-JIT即时编译器 14:49 原理篇-09-JIT即时编译器优化手段1-方法内联 16:49 原理篇-10-JIT即时编译器优化手段2-逃逸分析 09:03 原理篇-11-g1垃圾回收器原理-年轻代回收 27:57 原理篇-12-g1垃圾回收器原理-混合回收 17:24 原理篇-13-ZGC原理 26:27 原理篇-14-ShenandoahGC原理 09:39 面试篇-01-什么是JVM 16:38 面试篇-02-字节码文件的组成 15:02 面试篇-03-什么是运行时数据区 20:09 面试篇-04-哪些区域会出现内存溢出 11:56 面试篇-05-JDK6-8内存区域上的不同 14:36 面试篇-06-类的生命周期 17:17 面试篇-07-什么是类加载器 17:05 面试篇-08-什么是双亲委派机制 12:15 面试篇-09-如何打破双亲委派机制 18:10 面试篇-10-tomcat的自定义类加载器 31:18 面试篇-11-如何判断堆上的对象有没有被引用 10:05 面试篇-12-JVM中都有哪些引用类型 16:58 面试篇-13-theadlocal中为什么要使用弱引用 12:16 面试篇-14-有哪些垃圾回收算法 24:54 面试篇-15-有哪些常用的垃圾回收器 18:55 面试篇-16-如何解决内存泄漏问题 23:52 面试篇-17-常见的JVM参数 11:11 这是目前我学习的视频集合,要不要全看,或者少了什么,有哪些重要内容需要进行学习汇总或刷题或通过小实例验证
10-02
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值