Java Character源码剖析

Character类除了封装了一个char外,还封装了Unicode字符级别的各种操作,是Java文本处理的基础。下面结合源码分析Character的贡献。

Unicode

也许你没听过Unicode,但应该见过UTF-8。UTF-8(8-bit Unicode Transformation Format)是一种常用的Unicode字符编码方案之一。它使用变长编码方式,将Unicode码点编码成1至4个字节的序列。UTF-8编码保证了对ASCII字符的向后兼容性,因此在处理纯英文文本时,其存储效率与ASCII编码相同。

而Unicode是一种字符编码标准,它为世界上几乎所有的字符分配了一个唯一的数字标识符。它旨在为文字的表示提供一种统一的方式,使得不同国家和语言的字符都能被正确地编码和解码。

在字符编码中,有两个重要的概念:代码点(code point)和代码单元(code unit)。

代码点是Unicode标准中给每个字符分配的唯一整数值。它对应于一个字符的抽象概念,表示文本中的一个字符。Unicode的代码点范围从U+0000到U+10FFFF。每个代码点都有一个唯一的编号,可以用十六进制形式表示,例如U+0041表示字符'A'。

代码单元是计算机中存储和处理字符时使用的最小单位。在Unicode中,代码单元的大小可以是8位(1个字节)或16位(2个字节)。在Java中,字符是使用Unicode编码表示的。Java的char类型是16位无符号整数(即UTF-16) ,用于表示一个Unicode字符。因此,Java中的字符串实际上是由一系列Unicode字符组成的。

然而,Unicode中的某些字符需要用多个代码单元来表示,这种情况下被称为代理对(surrogate pair)。代理对由一个高位代理项(High Surrogate,范围U+D800至U+DBFF)和一个低位代理项(Low Surrogate,范围U+DC00至U+DFFF)组成,它们一起表示一个字符。通过组合高位和低位代理项可以得到完整的代码点。

比如 ☺️ 的码点U+1F60A可以通过代理对的方式表示:

  1. 计算出该码点在辅助平面中的偏移量:U+1F60A - U+10000 = 0xF60A
  2. 将偏移量拆分为高位和低位代理项:
    • 高位代理项:0xD83D (U+D800 + 0xF60A >> 10)
    • 低位代理项:0xDE0A (U+DC00 + 0xF60A & 0x3FF)
  3. 使用这两个代理项来构成代理对,从而表示 ☺️。
int codePoint = 0x1F60A;
char[] surrogatePair = Character.toChars(codePoint);
System.out.println("UTF-16 编码: " + new String(surrogatePair));

检查代码点和字符

Character类中有很多相关静态方法,以下是对code point和char的检查

//判断一个int是不是一个有效的代码点,小于等于0x10FFFF的为有效,大于的为无效
public static boolean isValidCodePoint(int codePoint)
//判断一个int是不是BMP字符,小于等于OxFFFF的为BMP字符,大于的不是
public static boolean isBmpCodePoint(int codePoint)
//判断一个int是不是增补字符,0x010000~0X10FFFF为增补字符
public static boolean isSupplementaryCodePoint(int codePoint)
//判断char是否是高代理项,0xD800~0xDBFF为高代理项
public static boolean isHighSurrogate(char ch)
//判断char是否为低代理项,0xDC00~0xDFFF为低代理项
public static boolean isLowSurrogate(char ch)
//判断char是否为代理项,char为低代理项或高代理项,则返回true
public static boolean isSurrogate(char ch)
//判断两个字符high和low是否分别为高代理项和低代理项
public static boolean isSurrogatePair(char high, char low)
//判断一个代码点由几个char组成,增补字符返回2,BMP字符返回1
public static int charCount(int codePoint)

代码点和字符的互转

之前仅针对int和char之间的转换相信大家都很熟悉,就是参照ASCII码

从代码点到字符的转换:

int codePoint = 65; // 代码点(Unicode码点)
char c = (char) codePoint; // 将代码点转换为字符
System.out.println(c); // 输出字符 'A'

从字符到代码点的转换:

char c = 'A'; // 字符
int codePoint = c; // 将字符转换为代码点(Unicode码点)
System.out.println(codePoint); // 输出代码点 65

而有了低代理项和高代理项后,需要用复杂的公式转换。这个公式的基本思想是将高代理项和低代理项分别减去一个偏移量(0xD8000xDC00),然后将它们组合起来生成代码点。

public static int toCodePoint(char high, char low) {
    return ((high - 0xD800) << 10) + (low - 0xDC00) + 0x10000;
}

下面是其他的处理函数

//根据高代理项high和低代理项1ow生成代码点,这个转换有个公式,这个方法封装了这个公式
public static int toCodePoint(char high, char low)
//根据代码点生成char数组,即UTF-16表示,如果code point为BMP字符,则返回的char
//数组长度为1,如果为增补字符,长度为2,char[0]为高代理项,char[1]为低代理项
public static char[] toChars(int codePoint)
//将代码点转换为char数组,与上面方法类似,只是结果存入指定数组dst的指定位置index
public static int toChars(int codePoint, char[] dst, int dstIndex)
//对增补字符code point,生成低代理项
public static char lowSurrogate(int codePoint)
//对增补字符code point,生成高代理项
public static char highSurrogate(int codePoint)

Unicode字符属性

Unicode在给每个字符分配一个编号之外,还分配了一些属性Unicode给每个字符分配了一个类型,这个类型是非常重要的,很多其他检查和操作都是基于这个类型的。getType方法的参数可以是int类型的code point,也可以是char类型。char类型只能处理BMP字符,而int类型可以处理所有字符。Character类中很多方法都是既可以接受int类型,也可以接受char类型。

//获取字符类型
public static int getType(int codePoint)
public static int getType(char ch)

根据这个类型属性,可以获得字符的信息

//检查字符是否在Unicode中被定义:
public static boolean isDefined(int codePoint)
//检查是否为字母:
public static boolean isLetter(int codePoint)
//检查是否为字母或数字:
public static boolean isLetterOrDigit(int codePoint)
//检查是否为字母(Alphabetic):
public static boolean isAlphabetic(int codePoint)
//检查是否为空格字符:
public static boolean isSpaceChar(int codePoint)
//匹配实际产生空格效果的字符,如Tab控制键't'。更常用的检查空格的方法:
public static boolean isWhitespace(int codePoint)
//检查是否为小写字符:
public static boolean isLowerCase(int codePoint)
//检查是否为大写字符:
public static boolean isUpperCase(int codePoint)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/375124.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

记一次VulnStack渗透

信息收集 netdiscover的主机发现部分不再详解&#xff0c;通过访问端口得知20001-2003端口都为web端口&#xff0c;所以优先考虑从此方向下手 外网渗透 GetShell Struct漏洞 访问2001端口后&#xff0c;插件Wappalyzer爬取得知这是一个基于Struct的web站点&#xff0c;直接…

微软Windows生态是怎么打造成功的?

&#xff08;1&#xff09;2015年Windows10&#xff1a;兼容性 我不得不再次佩服一下微软&#xff0c;Windows10是2015年出品的&#xff0c;但是仍然能正常运行绝大多数的Windows95软件&#xff0c;不用做任何的适配修改&#xff0c;连重新编译都不用&#xff0c;运行照样正常。…

游戏服务器租用多少钱一年(游戏服务器租用多少钱合适)

2024年更新腾讯云游戏联机服务器配置价格表&#xff0c;可用于搭建幻兽帕鲁、雾锁王国等游戏服务器&#xff0c;游戏服务器配置可选4核16G12M、8核32G22M、4核32G10M、16核64G35M、4核16G14M等配置&#xff0c;可以选择轻量应用服务器和云服务器CVM内存型MA3或标准型SA2实例&am…

TDengine用户权限管理

Background 官方文档关于用户管理没有很详细的介绍&#xff0c;只有零碎的几条&#xff0c;这里记录下方便后面使用。官方文档&#xff1a;https://docs.taosdata.com/taos-sql/show/#show-users 1、查看用户 show users;super 1&#xff0c;表示超级用户权限 0&#xff0c;表…

学会这一招,轻松玩转小程序自动化

♥ 前 言 app中混合应用自动化测试 会这一招&#xff0c;轻松玩转 app 中混合应用自动化测试 上次给同学们介绍了 app 中混合应用自动化怎么做&#xff0c;今天我们再来学习下&#xff0c;app 自动化之——小程序自动化。 一、环境要求 微信版本 weixin7.0.10.apk 版本&…

K8S部署Harbor镜像仓库(含离线安装包harbor-offline-installer国内下载链接)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

2024/2/6学习记录

ts 因为已经学习过了 js &#xff0c;下面的都是挑了一些 ts 与 js 不同的地方来记录。 安装 npm install -g typescript 安装好之后&#xff0c;可以看看自己的版本 ts基础语法 模块 函数 变量 语法和表达式 注释 编译 ts 文件需要用 tsc xxx.ts &#xff0c;js 文件…

一句话总结Docker与K8S的关系

一句话总结&#xff1a;Docker只是容器的一种&#xff0c;它面向的是单体&#xff0c;K8S可以管理多种容器&#xff0c;它面向的是集群&#xff0c;Docker可以作为一种容器方案被K8S管理。下文继续具体介绍。 1、容器的核心概念 介绍这几个核心概念&#xff1a;OCI、CR、Runc、…

打包 iOS 的 IPA 文件

目录 摘要 引言 准备 选择证书类型 创建应用程序 设置应用程序标识和证书 配置构建设置 构建应用程序 导出IPA 签名和导出 代码案例演示 完成 总结 参考资料 摘要 本篇博客将为您介绍如何打包iOS的IPA文件。从APP提交、创建应用程序、设置应用程序标识和证书、配…

OCR文本纠错思路

文字错误类别&#xff1a;多字 少字 形近字 当前方案 文本纠错思路 简单&#xff1a; 一、构建自定义词典&#xff0c;提高分词正确率。不在词典中&#xff0c;也不是停用词&#xff0c;分成单字的数据极有可能是错字&#xff08;少部分可能是新词&#xff09;。错字与前后的…

深入探究:JSONCPP库的使用与原理解析

君子不器 &#x1f680;JsonCPP开源项目直达链接 文章目录 简介Json示例小结 JsoncppJson::Value序列化Json::Writer 类Json::FastWriter 类Json::StyledWriter 类Json::StreamWriter 类Json::StreamWriterBuilder 类示例 反序列化Json::Reader 类Json::CharReader 类Json::Ch…

消息中间件之RocketMQ源码分析(六)

Consumer消费方式 RocketMQ的消费方式包含Pull和Push两种 Pull方式。 用户主动Pull消息&#xff0c;自主管理位点&#xff0c;可以灵活地掌控消费进度和消费速度&#xff0c;适合流计算、消费特别耗时等特殊的消费场景。 缺点也显而易见&#xff0c;需要从代码层面精准地控制…

python+django+vue高校学生社团管理系统euw84

社团管理系统是一个B/S模式系统&#xff0c;采用django框架&#xff0c;MySQL数据库设计开发&#xff0c;充分保证系统的稳定性。在系统的测试环节&#xff0c;主要通过功能测试的方式&#xff0c;验证系统的功能设计是否符合要求&#xff0c;能否满足使用需求。本社团管理系统…

【实训】自动运维ansible实训(网络管理与维护综合实训)

来自即将退役学长的分享&#xff0c;祝学弟学妹以后发大财&#xff01; 一 实训目的及意义 1.1 实训目的 1、熟悉自动化运维工具&#xff1a;实训旨在让学员熟悉 Ansible 这一自动化运维工具。通过实际操作&#xff0c;学员可以了解 Ansible 的基本概念、工作原理和使用方法…

text-generation-webui搭建大模型运行环境与踩坑记录

text-generation-webui搭建大模型运行环境 text-generation-webui环境初始化准备模型启动项目Bug说明降低版本启动项目 text-generation-webui text-generation-webui是一个基于Gradio的LLM Web UI开源项目&#xff0c;可以利用其快速搭建部署各种大模型环境。 环境初始化 下载…

【VSTO开发-WPS】下调试

重点2步&#xff1a; 1、注册表添加 Windows Registry Editor Version 5.00[HKEY_CURRENT_USER\Software\kingsoft\Office\WPP\AddinsWL] "项目名称"""2、visual studio 运行后&#xff0c;要选中附加到调试&#xff0c;并指定启动项目。 如PPT输入WPP搜…

考研高数(一阶导与二阶导)

一阶导数 导数最大的作用是判断复杂函数的单调性&#xff0c;则可用一阶导判断原函数的单调性。 一阶导数>0&#xff1a;函数单调递增&#xff1b; 一阶导数<0&#xff1a;函数单调递减&#xff1b; 一阶导数0&#xff1a;函数是常函数。 也可以通过一阶导数0的根来…

一致性哈希算法

在分布式领域中各技术组件都有实现KV形式的存储&#xff0c;在实现各类工作能力的同时还简化了算法实现。以Raft分布式协议为例&#xff0c;它通过在领导者采用KV存储来简化算法实现和共识协商&#xff0c;但同时也限制所有写请求只能在领导者节点上进行处理&#xff0c;从而导…

TS项目实战二:网页计算器

使用ts实现网页计算器工具&#xff0c;实现计算器相关功能&#xff0c;使用tsify进行项目编译&#xff0c;引入Browserify实现web界面中直接使用模块加载服务。   源码下载&#xff1a;点击下载 讲解视频 TS实战项目四&#xff1a;计算器项目创建 TS实战项目五&#xff1a;B…

龙芯安装使用搜狗输入法

CPU&#xff1a;龙芯3A6000 操作系统&#xff1a;Loongnix 桌面主题&#xff1a;Cartoon 龙芯系统切换输入法的按键一般为&#xff1a;Ctrl空格。 1 安装搜狗输入法 进入Loongnix系统自带的龙芯应用合作社&#xff0c;寻找搜狗输入法&#xff0c;点击安装。 按下Ctrl空格&…