从String源码看Java中的编码

简介: 从String源码的一个构造方法说起public String(int[] codePoints, int offset, int count) {}what?codePoints是什么鬼?为了看懂这个源码,有必要了解一个这个codePoints(代码点)的相关知识,其实整个String源码都会不少的涉及的java编码的相关知识,比如indexOf(int ch, int fromIndex)。

从String源码的一个构造方法说起

public String(int[] codePoints, int offset, int count) {}

what?codePoints是什么鬼?为了看懂这个源码,有必要了解一个这个codePoints(代码点)的相关知识,其实整个String源码都会不少的涉及的java编码的相关知识,比如indexOf(int ch, int fromIndex)

img_b72bf222324c35fef5c1ea1e2c387845.png
一脸懵逼

为什么会有Unicode

​ 学C/C++的时候我们知道了ASCII码,但这个能表示的字符有限,后来又出现了一些乱七八糟的编码表,Unicode就是企图统一一下编码而产生的。

Unicode的介绍

​ Unicode的第一个版本是用2个字节来编码所有的字符的,因为编码者们认为2^16=65536能容纳世界上所有语言,后来他们发现他们错了,哈哈哈,第二个版本就用4个字节来编码所有字符,这个后面说。

img_bea3dbc3aaed270db06e274576c2d1cb.jpe

先以第一个版本来说,用2个字节来编码所有字符(这个要很清晰,不然会有点懵),正好UTF-16也是这么弄的,大家误解就以为Unicode就是UTF-16。这里会涉及两个步骤,一个步骤是字符与编码一一对应的问题,如a对97,b对98如此;另一个是如何将编码的二进制这些01串保存起来的问题,这就实现了UTF(unicode transformation format),有UTF-8,UTF-16……

UTF-8与UTF-16

​ UTF16很好理解,在第一个版本的Unicode中,就是2个字节保存一个字符。UTF8就不同,它可能用1个/2个/3个来表示。那我怎么知道它用来多少个自己来表示呢?这就需要一个规定:

  1. 0开头的,就表示1个字节表示一个字符,即0xxx xxxx,如0101 0011
  2. 110x xxxx 10xx xxxx这种表示把2个字节当成一个单元,表示一个字符。
  3. 1110 xxxx 10xx xxxx 10xx xxxx这种表示3个字节当成一个单元,表示一个字符。

由上面我们可以看出UTF-8需要判断每个字节中的开头标志信息,所以如果一当某个字节在传送过程中出错了,就会导致后面的字节也会解析出错.而UTF-16不会判断开头标志,即使错也只会错一个字符,所以容错能力强.

​ 从上面可以看出,当1个字节表示一个字符时,能表示2^7=128个字符,2个字节表示时能表示2048个字符,3个单元表示时能表示65536个字符。由于"汉"的编码27721大于2048了所有两个字节还不够,只能用三个字节来表示。

接着看看第二个版本

​ 相关规定:

  • Unicode 统一编码 0x000000-0x10ffff,其中0x0000-0xffff为基本多语言平面字符

  • bmp 基本多语言平面字符,对应Unicode中0x0000-0xffff

  • Unicode码空间为U+0000到U+10FFFF,一共有17个平面,每个平面可容下65536个code point。也就是17 * 65536=1,114,112。但是其中的U+D800-U+DFFF作为UTF-16编码代理区保留,也就是它们不会作为code point分配给字符,保留数目是8 * 256=2048。

    看到这里,我们可以知道:

  • 如果在BMP级别中,那么16bits(一个代码单元)就足够表示出字符的Unicode值。

  • 那不在的呢,就属于增补字符了。那就是需要4个字节来表示,那4个字节为啥不是能表示0x00000000-0xffffffff个字符呢,只能表示到0x10ffff呢,这就有点像UTF-8的意思了,占用几个位置来表示我需要用4个字节来显示这个字符,那么需要占用多少位呢?因为只需要表示0x10 ffff - 0x10000 = 0xf ffff即可,就是20位,也就是说,虽然你给我分配4个字节32位这么多,但我只需要20位就足够表示0x10000~0x10FFFF,那剩下12位怎么办呢,这样吧,每2个字节用6位作为代理区,剩下10位用作编码,这就是U+D800-U+DFFF作为UTF-16编码代理区保留的规定了。

  • 那为什么是0xD800~0xDFFF呢,我们来看看,假设我们是编码者,我们现在要留一段来做代理区,假设我做代理区的起点选了0xD800吧,对应的是1100 1000 0000 0000,那我把剩下10位编码上去,就能表示:1101 1000 0000 0000~1101 1011 1111 1111即0xD800~ 0xDBFF,这个就算高位代理区了,然后同理,0xDC00~ 0xDFFF就算地位代理区了。

  • 好了,BMP区域有2048个编码被用作代理区了,所以它们是不能用来表示任何字符的。

Last but not least

简要的讨论了一下以String构造方法引出的一点问题,其实java的编码还是蛮复杂的,一口气说太多太复杂,估计大脑cpu也不够用了。

目录
相关文章
|
2月前
|
编解码 Java 开发者
Java String类的关键方法总结
以上总结了Java `String` 类最常见和重要功能性方法。每种操作都对应着日常编程任务,并且理解每种操作如何影响及处理 `Strings` 对于任何使用 Java 的开发者来说都至关重要。
325 5
|
8月前
|
前端开发 Java 关系型数据库
基于Java+Springboot+Vue开发的鲜花商城管理系统源码+运行
基于Java+Springboot+Vue开发的鲜花商城管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的鲜花商城管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。技术学习共同进步
570 7
|
8月前
|
消息中间件 算法 安全
JUC并发—1.Java集合包底层源码剖析
本文主要对JDK中的集合包源码进行了剖析。
|
4月前
|
存储 SQL 缓存
Java字符串处理:String、StringBuilder与StringBuffer
本文深入解析Java中String、StringBuilder和StringBuffer的核心区别与使用场景。涵盖字符串不可变性、常量池、intern方法、可变字符串构建器的扩容机制及线程安全实现。通过性能测试对比三者差异,并提供最佳实践与高频面试问题解析,助你掌握Java字符串处理精髓。
|
3月前
|
存储 小程序 Java
热门小程序源码合集:微信抖音小程序源码支持PHP/Java/uni-app完整项目实践指南
小程序已成为企业获客与开发者创业的重要载体。本文详解PHP、Java、uni-app三大技术栈在电商、工具、服务类小程序中的源码应用,提供从开发到部署的全流程指南,并分享选型避坑与商业化落地策略,助力开发者高效构建稳定可扩展项目。
|
5月前
|
自然语言处理 Java Apache
在Java中将String字符串转换为算术表达式并计算
具体的实现逻辑需要填写在 `Tokenizer`和 `ExpressionParser`类中,这里只提供了大概的框架。在实际实现时 `Tokenizer`应该提供分词逻辑,把输入的字符串转换成Token序列。而 `ExpressionParser`应当通过递归下降的方式依次解析
372 14
|
7月前
|
JavaScript Java 关系型数据库
家政系统源码,java版本
这是一款基于SpringBoot后端框架、MySQL数据库及Uniapp移动端开发的家政预约上门服务系统。
237 6
家政系统源码,java版本
|
7月前
|
供应链 JavaScript 前端开发
Java基于SaaS模式多租户ERP系统源码
ERP,全称 Enterprise Resource Planning 即企业资源计划。是一种集成化的管理软件系统,它通过信息技术手段,将企业的各个业务流程和资源管理进行整合,以提高企业的运营效率和管理水平,它是一种先进的企业管理理念和信息化管理系统。 适用于小微企业的 SaaS模式多租户ERP管理系统, 采用最新的技术栈开发, 让企业简单上云。专注于小微企业的应用需求,如企业基本的进销存、询价,报价, 采购、销售、MRP生产制造、品质管理、仓库库存管理、财务应收付款, OA办公单据、CRM等。
446 23
|
6月前
|
存储 安全 Java
Java 集合面试题从数据结构到 HashMap 源码剖析详解及长尾考点梳理
本文深入解析Java集合框架,涵盖基础概念、常见集合类型及HashMap的底层数据结构与源码实现。从Collection、Map到Iterator接口,逐一剖析其特性与应用场景。重点解读HashMap在JDK1.7与1.8中的数据结构演变,包括数组+链表+红黑树优化,以及put方法和扩容机制的实现细节。结合订单管理与用户权限管理等实际案例,展示集合框架的应用价值,助你全面掌握相关知识,轻松应对面试与开发需求。
354 3