String是一个奇怪的引用类型

简介: 今天从两张诡异的编程图聊到了String的不可变性、内存分布, 延伸谈到了String不可变性的设计设计考量(有先射箭再画靶的嫌疑☺️)针对频繁修改的String如何做内存优化

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


df7e016b8b9928349d6499287181afb7.png


bc53cf357f11fd484c3beb56bd0beaf0.png


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


这个例子,string是纯粹的引用类型,但是在函数传值时类似于值传递;我之前给前后示例的内存变化图吧:


7c5f07437f2aeb2b70975529e46355e9.png


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


为什么被设计成不可变。


这个我还真的搜索了一下[1]


总结起来:


  1. string 被设计为不可变, 是因为 string在现代任何语言中,使用很频繁:多个对象可能都是这个字符面值, 然后就设计一个Pool来存储string。既然pool里面共享字符面值,修改的时候又不能影响到别人,那就只好重新拷贝产生新的字符面值。


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


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


  • 一个有意思的现象是: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打印结果为:222


c75d719a98f68eab826467aa17330147.png


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());



07a31e57c712f52e13e2dbcfb73cfcf0.png


总结输出


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


  1. String不可变性的设计设计考量(有先射箭再画靶的嫌疑☺️)


  1. 针对频繁修改的String如何做内存优化
相关文章
|
存储 Java
基本类型、包装类型、引用类型、String等作为实参传递后值会不会改变?
基本类型、包装类型、String类型作为参数传递之后,在方法里面修改他们的值,原值不会改变!引用类型不一定,要看是怎么修改它的。
127 0
|
前端开发 JavaScript 索引
前端祖传三件套JavaScript的对象之常用引用类型的String
字符串是 JavaScript 中最常用的数据类型之一,作为 JavaScript 的基础之一,它拥有一系列的函数和方法,可以方便地完成各种字符串操作。在本文中,我们将深入探讨 JavaScript 字符串的对象类型,并介绍其中一些常用的引用类型。
92 0
C# string特殊引用类型
一、string的确是引用类型 常规上是这样定义的:     string是引用类型,但是其又具有值类型的一些特性。   static void Main(string[] args) ...
861 0
string 是值类型,还是引用类型(.net)
一. string 类型的用法比较像值类型 稍微有点.NET 编程知识的人都知道 string是引用类型。我为什么还有此一问?因为string的使用非常像值类型。举个例子: string str = "abc"; Test(str); MessageBox.Show(str); private void Test(string str) {      str = str + "de"; }   运行上面的代码你会发现 str始终是abc,这就有点像值类型。
987 0
|
3月前
|
Java 索引
java基础(13)String类
本文介绍了Java中String类的多种操作方法,包括字符串拼接、获取长度、去除空格、替换、截取、分割、比较和查找字符等。
44 0
java基础(13)String类
|
23天前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
37 2
|
2月前
|
Java
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
本文深入探讨了Java中方法参数的传递机制,包括值传递和引用传递的区别,以及String类对象的不可变性。通过详细讲解和示例代码,帮助读者理解参数传递的内部原理,并掌握在实际编程中正确处理参数传递的方法。关键词:Java, 方法参数传递, 值传递, 引用传递, String不可变性。
67 1
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
|
2月前
|
安全 Java 测试技术
Java零基础-StringBuffer 类详解
【10月更文挑战第9天】Java零基础教学篇,手把手实践教学!
49 2
|
3月前
|
安全 Java
String类-知识回顾①
这篇文章回顾了Java中String类的相关知识点,包括`==`操作符和`equals()`方法的区别、String类对象的不可变性及其好处、String常量池的概念,以及String对象的加法操作。文章通过代码示例详细解释了这些概念,并探讨了使用String常量池时的一些行为。
String类-知识回顾①