开局两张图,内容全靠刷!

马甲哥看到这样的现象,一开始还是有点懵逼。

这个例子,string是纯粹的引用类型,但是在函数传值时类似于值传递;

我之前给前后示例的内存变化图吧:

根因就是大多数高级语言都把String设计成不可变的:由一个字符串池管理字符串面值。

为什么被设计成不可变。

这个我还真的搜索了一下

总结起来:

  1. string 被设计为不可变, 是因为 string在现代任何语言中,使用很频繁:多个对象可能都是这个字符面值, 然后就设计一个Pool来存储string。

    既然pool里面共享字符面值,修改的时候又不能影响到别人,那就只好重新拷贝产生新的字符面值。

  2. 不可变资源消除了多线程中的资源竞争,对于文本的修改都会导致创建新空间,因此在多个线程同时访问文本无需设置锁,这对频繁使用的string开发者很友好。

  3. 字符串不变性对于[在哈希表中使用字符串作为键]很友好,需要计算哈希值的对象必须是不可变的,以确保哈希值不变。

  • 一个有意思的现象是: String虽然是引用类型,字符串对比时却表现的像值类型
string str1="FooFoo";
string strFoo="Foo";
string str2= strFoo + strFoo;
return str1 == str2; // 返回true

正因为String不可变性 & Pool的机制,频繁变更字符串,会在池中产生很多临时的不用的字符串,所以我们有了缓解的套路:

StringBuilder

代表可变的字符串,一旦修改不会尝试创建新对象,而是动态扩展内存

var ss = new StringBuilder("Hello ", 100);  // 初次字符容量100
ss.Append("www.cnblogs.com");
Console.WriteLine(ss.ToString()); // ss打印结果为:Hello www.cnblogs.com

Span

Span该出圈了,

Span提供对内存连续区域的类型安全访问,该内存可以位于堆、堆栈、甚至是非托管内存;

与String不可变性相关的是ReadOnlySpan(值类型), 提供内存数据的只读视图,每次切片不会产生新对象,而是在存在的连续空间上创造新的视图。

var text = "https://www.cnblogs.com/JulianHuang/p/14817621.html";
ReadOnlySpan<char> nameSpan = text.AsSpan(8, 15);
nameSpan = nameSpan.Slice(4,7);
Console.WriteLine(nameSpan.ToString());

总结输出

今天从两张诡异的编程图聊到了String的不可变性、内存分布, 延伸谈到了

  1. String不可变性的设计设计考量(有先射箭再画靶的嫌疑️)
  2. 针对频繁修改的String如何做内存优化

不是自吹,文章内容在业界相当硬核(多次被各大佬/CSDN点赞/转载),阅读/关注不是目的,更希望得到更多的阅读反馈、互相促进认知的提升(相当真诚️)。

String 是一个奇怪的引用类型的更多相关文章

  1. SpannableString的一个奇怪的问题

    今天使用spannableString遇到一个奇怪的问题,就是在setspan的时候,原本可以写成 spannableString.setSpan(new RelativeSizeSpan(0.5f) ...

  2. String为值类型还是引用类型

    关于String为值类型还是引用类型的讨论一直没有平息,最近一直在研究性能方面的问题,今天再次将此问题进行一次明确.希望能给大家带来点帮助. 如果有错误请指出. 来看下面例子: //值类型 int a ...

  3. 一个奇怪的JS函数

    今天在分析一个jQuery插件源码的时候,发现了一个奇怪的函数. 这个函数的目的是为数字补零,如传入7,输出07,传入12输出12.由于是对时间补零,只截取后两位. // add leading ze ...

  4. string 是值类型,还是引用类型(.net)[转]

    转自http://hi.baidu.com/newfzks/item/b805f0f4edb0810dd89e7290 string 是值类型,还是引用类型(.net) 一. string 类型的用法 ...

  5. 转:C# String为值类型还是引用类型

    关于String为值类型还是引用类型的讨论一直没有平息,最近一直在研究性能方面的问题,今天再次将此问题进行一次明确.希望能给大家带来点帮助,如果有错误请指出. 来看下面例子: //值类型 int a ...

  6. ERROR: “System.Web.Mvc.Controller.File(string, string, string)”是一个“方法”

    ERROR: “System.Web.Mvc.Controller.File(string, string, string)”是一个“方法”,这在给定的上下文中无效 这是一个与Controller.F ...

  7. MinGW 和 MSVC 下,使用 FILE 类型的一个奇怪的问题

    今天遇到一个奇怪的问题. 开发环境: 1. Eclipse CDT,使用 MinGW 的 gcc 编译器和函数库 2. Visual Studio 2008 问题描述: 在 eclipse cdt 中 ...

  8. 遇到delphi连接sql一个奇怪的问题:未指定的错误,加大了命令的等待时间为600即可了

    遇到delphi连接sql一个奇怪的问题:未指定的错误,加大了命令的等待时间为600即可了 找了一下午没解决.

  9. 【Windows 7】发现一个奇怪的现象

    最近在Windows7-32位操作系统上发现一个奇怪的现象,不知道64位操作系统上会不会发生这个现象.这个现象就是:如果系统上的一个或多个账户没有设置密码,那么在此条件下终止winlogon.exe进 ...

随机推荐

  1. Jmeter对数据库批量增删改查

    本文主要的内容是使用Jmeter对数据库进行数据的操作,包括单条语句的增删改查,多条语句的增删改查,本文主要介绍操作流程,关于流程的运作原理,对原理感兴趣的同学可自行查阅资料. 首先需要准备一个数据库 ...

  2. JDBC_14_使用JDBC工具类实现模糊查询

    使用JDBC工具类实现模糊查询 代码: import java.sql.*; /** * 模糊查询 * 测试DBUtils */ public class JDBCTest09 { public st ...

  3. Day13_67_interrupt() 方法

    interrupt() 方法 中断线程 * interrupt()方法的简单理解 - interrupt() 方法只是改变线程的阻塞状态而已,让一个正在阻塞状态的线程,恢复执行.但是它不会中断一个正在 ...

  4. java面试一日一题:mysql中的自增主键

    问题:请讲下mysql中的自增主键 分析:该问题主要考察对mysql中自增主键的掌握,使用场景及如何设置 回答要点: 主要从以下几点去考虑 1.什么自增主键 2.使用场景是什么: 3.innodb_a ...

  5. 02- Python的版本

    python的官网 https://www.python.org/ Python的版本 python  v2.7(2020结束维护) python  v.3.5(当前使用的版本) python  v3 ...

  6. spring boot 项目从配置文件中读取maven 的pom.xml 文件标签的内容。

    需求: 将pom.xml 文件中的版本号读取到配置文件并打印到日志中. 第一步: 在pom.xml 中添加以下标签. 第二步: 将version 标签的值读取到配置文件中 这里使用 @@  而不是  ...

  7. Intel汇编语言程序设计学习-第五章 过程-上

    过程 5.1  简介 需要阅读本章的理由可能很多: 1.读者可能想要学习如何在汇编语言中进行输入输出. 2.应该了解运行时栈(runtime stack),运行时栈是子过程(函数)调用以及从子过程返回 ...

  8. 使用docker-compose.yml快速搭建Linux/Mac开发/生产环境

    传送门 点击进入Github,https://github.com/ovim/dockerfiles 简单介绍 Dockerfiles 搭建基础公用环境包,方便使用,支持业务不断的提升而需要一些软件的 ...

  9. linux 发送邮件

    参考资料:https://www.cnblogs.com/imweihao/p/7250500.html https://blog.csdn.net/liang19890820/article/det ...

  10. Vue3能不能用到生产环境?

    最近,有不少朋友问我:"十三,看你写了几个Vue3的项目,你觉得Vue3能用到生产环境了吗?"结合自己的想法和尤大直播说的话,给一点建议. 别问我!没结果,除非花手摇过我. 我不是 ...