为什么Swift中的String类型不属于Array类型?
为什么字符串不能直接用索引访问单个Unicode字符?
常被提及的标准答案:这是因为字符串的字符内容是一组长度可能不同的Unicode对象。
我一直觉得这个解答根本站不住脚——字符数组本身就是Unicode字符的数组啊!明明只要给String做个简单扩展,就能实现用大家熟悉的索引方式访问单个字符的功能。
显然我没抓住问题的核心,要是真有合理的原因,到底是什么?
核心原因:编码单元与Unicode码点的不对等
问题的关键在于底层存储的编码单元(Code Unit)和我们认知的Unicode字符(码点,Code Point)不是一一对应的。
多数编程语言的字符串底层采用UTF-16编码存储:
- 大部分常用Unicode字符(比如中文、英文)只需要1个UTF-16编码单元(2字节)就能表示;
- 但一些扩展字符(比如Emoji、部分生僻汉字、古文字)需要2个连续的编码单元(代理对,Surrogate Pair)才能表示完整的Unicode码点。
如果直接用索引访问字符串,拿到的是底层的单个编码单元,而非完整的Unicode字符。比如访问"😀"的索引0,得到的只是代理对的前半部分,根本不是一个可独立显示的有效字符。
为什么不做“简单扩展”实现按字符索引?
如果要实现按Unicode字符的索引访问,需要提前遍历整个字符串,把每个码点的位置记录下来——这会带来额外的内存开销和初始化时间。而编程语言默认的索引访问是直接操作底层存储的偏移量,效率极高,是性能和易用性之间的权衡选择。
毕竟大部分场景下,开发者要么是处理单编码单元的字符,要么是按顺序遍历字符串,而非随机访问某个位置的Unicode字符,所以优先保证底层操作的性能是更合理的设计。
内容的提问来源于stack exchange,提问作者adlibber
相关产品推荐
相关产品推荐

