前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >你说你是高工,char都没搞明白?!

你说你是高工,char都没搞明白?!

作者头像
吴延宝
发布2019-12-10 17:21:49
5700
发布2019-12-10 17:21:49
举报

阅读文本大概需要 5 分钟。

1

场 景

可能很多人对Java中最简单的Char类型根本不屑一顾,不就是一个字符吗?能玩出什么花来?真的是这样吗?真不一定,我见过的几个所谓的高工对char的理解可能都是在比较浅的水平。今天我就带大家从高工的角度思考这个简单的Java类型Char。

抛出问题:char如何存UTF-8字符?

2

UTF-8的由来

我们知道char是占两个字节的这个大家都知道,那UTF-8是什么呢?我们见得比较多,真正能说清楚的也不见得都能做到,在谈到UTF-8,我们不得不谈下Unicode,对于有些人来说Unicode可能稍微陌生点,但是说到ASCII码估计大家都知道。

简单说明下,我们知道计算机只能识别0和1,那么如何将我们这个世界中如此众多的文字呈现或者传播呢?美国人搞了个ASCII码就是一个将英文中的字母和一些特殊符号一共128种,使用7位二进制数字一一对应起来(说白了就是符号和7位二进制数的映射表)。

计算机中每八位二进制组成一个字节,它是计算机存储的最小单位。那么我们就可以用一个字节,最高为用0占位就完全足够标识英文中的任何字母了,这样就可以将英文在计算机中进行无压力的传播啦。(举个例子:字母“A”对应的二进制数为“01000001”即十进制的41)不错!这确实解决了美国的问题,可是世界上那么多国家的不同文字字符,不全是英文字母啊,这怎么行呢?

诶?!于是Unicode诞生了,他将编号范围扩大为0x000000~0x10FFFF来将世界上绝大多数的字符一一映射起来了。(Unicode可以说是对ASCII的补充,它也是一个字符集)比如中文“马”字,对应的唯一的Unicode编号为U+9A6C(16进制的表示方式)。

注意Unicode只是规定了字符的编号,并没有说明以什么样的形式存储,你可以说直接将编号转换成二进制进行存储不就可以了吗?不错,这么做确实可以,但是会带来几个问题?

  • 如何和ASCII码区分开来,计算机无法知道三个字节表示一个字符还是三个不同的字符?
  • 英文字符只需要一个字节就能表示完,如果Unicode统一说使用三个或者四个字节表示一个字符,那么对于英文字符存储空间造成很大的浪费

所以,出现了很多中来实现Unicode编码方式,UTF-8就是其中一种,他是一种变长的编码方式,比如英文字符他只使用一个字节存储,按照不同的Unicode编号,将他们划成四个范围,分别对应使用一个、两个、三个、四个字节。

而且编码规则简单,便于计算机判断当前多少个字节表示一个字符。比如检测到当前字节以0开头,那么当前字节就对应一个字符,如果开头是“1”,那么开头有多少个连续的“1”就表示当前这个字符占用多少个字节来存储。

以上,让我们知道了UTF-8其实就是Unicode字符集的一种编码方式,它可能会占用1~4个字节。

3

回归问题

那么,回到最初的问题,char是两个字节的,那么怎么使用char类型存UTF-8编码的字符呢(可能会是3或者4个字节)?

其实,我们可以定义一个char类型的数据赋值为'庆','庆'使用utf-8编码后为:e5ba86,不错是三个字节,三个字节怎么赋值给只占两个字节的char类型变量呢?可是事实是确实可以赋值的:

代码语言:javascript
复制
char test = '庆';

确实编译器没有报错,咋回事呢?这里就是大家的误区了。其实'庆'使用utf-16进行编码无论是大尾序utf-16BE(5E86)还是使用小尾序utf-16LE(865E)进行编码都是占用两个字节也就是一个字符的。

所以,我们要了解一个事实就是JVM中对char是使用UTF-16编码的。使用UTF-16的好处是大部分字符都能以固定两个字节存储,但是这样的坏处就是对于英文字符存储就造成浪费,但是为了解决这个问题,Java9以后对字符串做了优化,对于字符串里面都是拉丁字母或者ASCII码中的字符,不使用UTF-16编码存储,而是使用byte存储,这样可以省一部分空间。

4

发散性思考

emoji的表情"?"这个字符是占用几个字节呢,你可以这么赋值吗?

代码语言:javascript
复制
char emoji = '?';

发现编译器会报错的,我们换成下面的字符串的方式就没有问题了:

代码语言:javascript
复制
String emoji = "?";
System.out.println(emoji.length());
// 输出 2

这是为什么呢?感兴趣的读者可以去查下"?"这个表情的码点(Unicode中对应的值),使用UTF-16进行编码后看看有多少个字节,就知道为什么不能用char来存储了。

总结:本文看起来简单,其实讲的细节也是蛮多的。需要读者的基础知识比较扎实,对Unicode字符集,utf-8、utf-16编码都有一定的了解。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT烂笔头 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档