计算机程序的思维逻辑 (28) - 剖析包装类 (下)
yuyutoo 2024-10-21 12:02 2 浏览 0 评论
本节探讨Character类,它的基本用法我们在包装类第一节已经介绍了,本节不再赘述。Character类除了封装了一个char外,还有什么可介绍的呢?它有很多静态方法,封装了Unicode字符级别的各种操作,是Java文本处理的基础,注意不是char级别,Unicode字符并不等同于char,本节详细介绍这些方法以及相关的Unicode知识。
在介绍这些方法之前,我们需要回顾一下字符在Java中的表示方法,我们在第六节、第七节、第八节介绍过编码、Unicode、char等知识,我们先简要回顾一下。
Unicode基础
Unicode给世界上每个字符分配了一个编号,编号范围从0x000000到0x10FFFF。编号范围在0x0000到0xFFFF之间的字符,为常用字符集,称BMP(Basic Multilingual Plane)字符。编号范围在0x10000到0x10FFFF之间的字符叫做增补字符(supplementary character)。
Unicode主要规定了编号,但没有规定如果把编号映射为二进制,UTF-16是一种编码方式,或者叫映射方式,它将编号映射为两个或四个字节,对BMP字符,它直接用两个字节表示,对于增补字符,使用四个字节,前两个字节叫高代理项(high surrogate),范围从0xD800到0xDBFF,后两个字节叫低代理项(low surrogate),范围从0xDC00到0xDFFF,UTF-16定义了一个公式,可以将编号与四字节表示进行相互转换。
Java内部采用UTF-16编码,char表示一个字符,但只能表示BMP中的字符,对于增补字符,需要使用两个char表示,一个表示高代理项,一个表示低代理项。
使用int可以表示任意一个Unicode字符,低21位表示Unicode编号,高11位设为0。整数编号在Unicode中一般称为代码点(Code Point),表示一个Unicode字符,与之相对,还有一个词代码单元(Code Unit)表示一个char。
Character类中有很多相关静态方法,让我们来看一下。
检查code point和char
判断一个int是不是一个有效的代码单元:
public static boolean isValidCodePoint(int codePoint)
小于等于0x10FFFF的为有效,大于的为无效。
判断一个int是不是BMP字符:
public static boolean isBmpCodePoint(int codePoint)
小于等于0xFFFF的为BMP字符,大于的不是。
判断一个int是不是增补字符:
public static boolean isSupplementaryCodePoint(int codePoint)
0x010000和0X10FFFF之间的为增补字符。
判断char是否是高代理项:
public static boolean isHighSurrogate(char ch)
0xD800到0xDBFF为高代理项。
判断char是否为低代理项:
public static boolean isLowSurrogate(char ch)
0xDC00到0xDFFF为低代理项。
判断char是否为代理项:
public static boolean isSurrogate(char ch)
char为低代理项或高代理项,则返回true。
判断两个字符high和low是否分别为高代理项和低代理项:
public static boolean isSurrogatePair(char high, char low)
判断一个代码单元由几个char组成:
public static int charCount(int codePoint)
增补字符返回2,BMP字符返回1。
code point与char的转换
除了简单的检查外,Character类中还有很多方法,进行code point与char的相互转换。
根据高代理项high和低代理项low生成代码单元:
public static int toCodePoint(char high, char low)
这个转换有个公式,这个方法封装了这个公式。
根据代码单元生成char数组,即UTF-16表示:
public static char toChars(int codePoint)
如果code point为BMP字符,则返回的char数组长度为1,如果为增补字符,长度为2,char[0]为高代理项,char[1]为低代理项。
将代码单元转换为char数组:
public static int toChars(int codePoint, char[] dst, int dstIndex)
与上面方法类似,只是结果存入指定数组dst的指定位置index。
对增补字符code point,生成高代理项和低代理项:
public static char lowSurrogate(int codePoint) public static char highSurrogate(int codePoint)
按code point处理char数组或序列
Character包含若干方法,以方便按照code point来处理char数组或序列。
返回char数组a中从offset开始count个char包含的code point个数:
public static int codePointCount(char[] a, int offset, int count)
比如说,如下代码输出为2,char个数为3,但code point为2。
char chs = new char[3]; chs[0] = '马'; Character.toChars(0x1FFFF, chs, 1); System.out.println(Character.codePointCount(chs, 0, 3));
除了接受char数组,还有一个重载的方法接受字符序列CharSequence:
public static int codePointCount(CharSequence seq, int beginIndex, int endIndex)
CharSequence是一个接口,它的定义如下所示:
public interface CharSequence { int length; char charAt(int index); CharSequence subSequence(int start, int end); public String toString; }
它与一个char数组是类似的,有length方法,有charAt方法根据索引获取字符,String类就实现了该接口。
返回char数组或序列中指定索引位置的code point:
public static int codePointAt(char[] a, int index) public static int codePointAt(char[] a, int index, int limit) public static int codePointAt(CharSequence seq, int index)
如果指定索引位置为高代理项,下一个位置为低代理项,则返回两项组成的code point,检查下一个位置时,下一个位置要小于limit,没传limit时,默认为a.length。
返回char数组或序列中指定索引位置之前的code point:
public static int codePointBefore(char[] a, int index) public static int codePointBefore(char[] a, int index, int start) public static int codePointBefore(CharSequence seq, int index)
与codePointAt不同,codePoint是往后找,codePointBefore是往前找,如果指定位置为低代理项,且前一个位置为高代理项,则返回两项组成的code point,检查前一个位置时,前一个位置要大于等于start,没传start时,默认为0。
根据code point偏移数计算char索引:
public static int offsetByCodePoints(char[] a, int start, int count, int index, int codePointOffset) public static int offsetByCodePoints(CharSequence seq, int index, int codePointOffset)
如果字符数组或序列中没有增补字符,返回值为index+codePointOffset,如果有增补字符,则会将codePointOffset看做code point偏移,转换为字符偏移,start和count取字符数组的子数组。
比如,我们看如下代码:
char chs = new char[3]; Character.toChars(0x1FFFF, chs, 1); System.out.println(Character.offsetByCodePoints(chs, 0, 3, 1, 1));
输出结果为3,index和codePointOffset都为1,但第二个字符为增补字符,一个code point偏移是两个char偏移,所以结果为3。
字符属性
我们之前说,Unicode主要是给每个字符分配了一个编号,其实,除了分配编号之外,还分配了一些属性,Character类封装了对Unicode字符属性的检查和操作,我们来看一些主要的属性。
获取字符类型(general category):
public static int getType(int codePoint) public static int getType(char ch)
Unicode给每个字符分配了一个类型,这个类型是非常重要的,很多其他检查和操作都是基于这个类型的。
getType方法的参数可以是int类型的code point,也可以是char类型,char只能处理BMP字符,而int可以处理所有字符,Character类中很多方法都是既可以接受int,也可以接受char,后续只列出int类型的方法。
返回值是int,表示类型,Character类中定义了很多静态常量表示这些类型,下表列出了一些字符,type值,以及Character类中常量的名称:
字符 | type值 | 常量名称 |
'A' | 1 | UPPERCASE_LETTER |
'a' | 2 | LOWERCASE_LETTER |
'马' | 5 | OTHER_LETTER |
'1' | 9 | DECIMAL_DIGIT_NUMBER |
' ' | 12 | SPACE_SEPARATOR |
'\n' | 15 | CONTROL |
'-' | 20 | DASH_PUNCTUATION |
'{' | 21 | START_PUNCTUATION |
'_' | 23 | CONNECTOR_PUNCTUATION |
'&' | 24 | OTHER_PUNCTUATION |
'<' | 25 | MATH_SYMBOL |
'$' | 26 | CURRENCY_SYMBOL |
检查字符是否在Unicode中被定义:
public static boolean isDefined(int codePoint)
每个被定义的字符,其getType返回值都不为0,如果返回值为0,表示无定义。注意与isValidCodePoint的区别,后者只要数字不大于0x10FFFF都返回true。
检查字符是否为数字:
public static boolean isDigit(int codePoint)
getType返回值为DECIMAL_DIGIT_NUMBER的字符为数字,需要注意的是,不光字符'0','1',...'9'是数字,中文全角字符的0到9,即'0','1','9'也是数字。比如说:
char ch = '9'; //中文全角数字 System.out.println((int)ch+","+Character.isDigit(ch));
输出为:
65305,true
全角字符的9,Unicode编号为65305,它也是数字。
检查是否为字母(Letter):
public static boolean isLetter(int codePoint)
如果getType的返回值为下列之一,则为Letter:
UPPERCASE_LETTER LOWERCASE_LETTER TITLECASE_LETTER MODIFIER_LETTER OTHER_LETTER
除了TITLECASE_LETTER和MODIFIER_LETTER,其他我们上面已经看到过了,而这两个平时碰到的也比较少,就不介绍了。
检查是否为字母或数字
public static boolean isLetterOrDigit(int codePoint)
只要其中之一返回true就返回true。
检查是否为字母(Alphabetic)
public static boolean isAlphabetic(int codePoint)
这也是检查是否为字母,与isLetter的区别是,isLetter返回true时,isAlphabetic也必然返回true,此外,getType值为LETTER_NUMBER时,isAlphabetic也返回true,而isLetter返回false。Letter_NUMBER中常见的字符有罗马数字字符,如:'Ⅰ','Ⅱ','Ⅲ','Ⅳ'。
检查是否为空格字符
public static boolean isSpaceChar(int codePoint)
getType值为SPACE_SEPARATOR,LINE_SEPARATOR和PARAGRAPH_SEPARATOR时,返回true。这个方法其实并不常用,因为它只能严格匹配空格字符本身,不能匹配实际产生空格效果的字符,如tab控制键'\t'。
更常用的检查空格的方法
public static boolean isWhitespace(int codePoint)
'\t','\n',全角空格' ',和半角空格' '的返回值都为true。
检查是否为小写字符
public static boolean isLowerCase(int codePoint)
常见的主要就是小写英文字母a到z。
检查是否为大写字符
public static boolean isUpperCase(int codePoint)
常见的主要就是大写英文字母A到Z。
检查是否为表意象形文字
public static boolean isIdeographic(int codePoint)
大部分中文都返回为true。
检查是否为ISO 8859-1编码中的控制字符
public static boolean isISOControl(int codePoint)
我们在第6节介绍过,0到31,127到159表示控制字符。
检查是否可作为Java标示符的第一个字符
public static boolean isJavaIdentifierStart(int codePoint)
Java标示符是Java中的变量名、函数名、类名等,字母(Alphabetic),美元符号($),下划线(_)可作为Java标示符的第一个字符,但数字字符不可以。
检查是否可作为Java标示符的中间字符
public static boolean isJavaIdentifierPart(int codePoint)
相比isJavaIdentifierStart,主要多了数字字符,中间可以有数字。
检查是否为镜像(mirrowed)字符
public static boolean isMirrored(int codePoint)
常见镜像字符有 { } < > ,都有对应的镜像。
字符转换
Unicode除了规定字符属性外,对有大小写对应的字符,还规定了其对应的大小写,对有数值含义的字符,也规定了其数值。
我们先来看大小写,Character有两个静态方法,对字符进行大小写转换:
public static int toLowerCase(int codePoint) public static int toUpperCase(int codePoint)
这两个方法主要针对英文字符a-z和A-Z, 例如:toLowerCase('A')返回'a',toUpperCase('z')返回'Z'。
返回一个字符表示的数值:
public static int getNumericValue(int codePoint)
字符'0'到'9'返回数值0到9,对于字符a到z,无论是小写字符还是大写字符,无论是普通英文还是中文全角,数值结果都是10到35,例如,如下代码的输出结果是一样的,都是10。
System.out.println(Character.getNumericValue('A')); //全角大写A System.out.println(Character.getNumericValue('A')); System.out.println(Character.getNumericValue('a')); //全角小写a System.out.println(Character.getNumericValue('a'));
返回按给定进制表示的数值:
public static int digit(int codePoint, int radix)
radix表示进制,常见的有2/8/10/16进制,计算方式与getNumericValue类似,只是会检查有效性,数值需要小于radix,如果无效,返回-1,例如:
digit('F',16)返回15,是有效的,但digit('G',16)就无效,返回-1。
返回给定数值的字符形式
public static char forDigit(int digit, int radix)
与digit(int codePoint, int radix)相比,进行相反转换,如果数字无效,返回'\0'。例如,Character.forDigit(15, 16)返回'F'。
与Integer类似,Character也有按字节翻转:
public static char reverseBytes(char ch)
例如,翻转字符0x1234:
System.out.println(Integer.toHexString( Character.reverseBytes((char)0x1234)));
输出为3412。
小结
本节详细介绍了Characer类以及相关的Unicode知识,Character类在Unicode字符级别,而非char级别,封装了字符的各种操作,通过将字符处理的细节交给Character类,其他类就可以在更高的层次上处理文本了。
至此,关于包装类我们就介绍完了。下一节,让我们在Character的基础上,进一步探索字符串类String。
----------------
未完待续,查看最新文章,敬请关注微信公众号“老马说编程”(扫描下方二维码),从入门到高级,深入浅出,老马和你一起探索Java编程及计算机技术的本质。用心写作,原创文章,保留所有版权。
-----------
相关好评原创文章
相关推荐
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
-
Mysql和Oracle实现序列自增/*ORACLE设置自增序列oracle本身不支持如mysql的AUTO_INCREMENT自增方式,我们可以用序列加触发器的形式实现,假如有一个表T_WORKM...
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
-
概述今天主要简单介绍一下Oracle12c的一些新特性,仅供参考。参考:http://docs.oracle.com/database/121/NEWFT/chapter12102.htm#NEWFT...
- MySQL CREATE TABLE 简单设计模板交流
-
推荐用MySQL8.0(2018/4/19发布,开发者说同比5.7快2倍)或同类型以上版本....
- mysql学习9:创建数据库(mysql5.5创建数据库)
-
前言:我也是在学习过程中,不对的地方请谅解showdatabases;#查看数据库表createdatabasename...
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
-
执行"CREATETABLE新表ASSELECT*FROM原表;"后,新表与原表的字段一致,但主键、索引不会复制到新表,会把原表的表记录复制到新表。...
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
-
在街上看到的PandaDunk的超载可能让一些球鞋迷们望而却步,但Dunk的浪潮仍然强劲,看不到尽头。我们看到的很多版本都是为女性和儿童制作的,这种新配色为后者引入了一种令人耳目一新的新选择,而...
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
-
多功能雷达AN/SPY-1的特性和技术能力,该雷达已经在美国海军服役了30多年,其修改-AN/SPY-1A、AN/SPY-1B(V)、AN/SPY-1D、AN/SPY-1D(V),以及雷神...
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
-
全面分析汽车音响使用或安装技术常识一:主机是大多数人最熟习的音响器材,有关主机的各种性能及规格,也是耳熟能详的事,以下是一些在使用或安装时,比较需要注意的事项:LOUDNESS:几年前的主机,此按...
- 【推荐】ProAc Response系列扬声器逐个看
-
有考牌(公认好声音)扬声器之称ProAcTablette小音箱,相信不少音响发烧友都曾经,或者现在依然持有,正当大家逐渐掌握Tablette的摆位设定与器材配搭之后,下一步就会考虑升级至表现更全...
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
-
作者:初吻给了烟sco混迹张大妈时日不短了,手没少剁。家里有了汪星人,吸尘器使用频率相当高,偶尔零星打扫用卧式的实在麻烦(汪星人:你这分明是找借口,我掉毛是满屋子都有,铲屎君都是用卧式满屋子吸的,你...
- 专题|一个品牌一件产品(英国篇)之Quested(罗杰之声)
-
Quested(罗杰之声)代表产品:Q212FS品牌介绍Quested(罗杰之声)是录音监听领域的传奇品牌,由英国录音师RogerQuested于1985年创立。在成立Quested之前,Roger...
- 常用半导体中英对照表(建议收藏)(半导体英文术语)
-
作为一个源自国外的技术,半导体产业涉及许多英文术语。加之从业者很多都有海外经历或习惯于用英文表达相关技术和工艺节点,这就导致许多英文术语翻译成中文后,仍有不少人照应不上或不知如何翻译。为此,我们整理了...
- Fyne Audio F502SP 2.5音路低音反射式落地音箱评测
-
FyneAudio的F500系列,有新成员了!不过,新成员不是新的款式,却是根据原有款式提出特别版。特别版产品在原有型号后标注了SP字样,意思是SpecialProduction。Fyne一共推出...
- 有哪些免费的内存数据库(In-Memory Database)
-
以下是一些常见的免费的内存数据库:1.Redis:Redis是一个开源的内存数据库,它支持多种数据结构,如字符串、哈希表、列表、集合和有序集合。Redis提供了快速的读写操作,并且支持持久化数据到磁...
- RazorSQL Mac版(SQL数据库查询工具)
-
RazorSQLMac特别版是一款看似简单实则功能非常出色的SQL数据库查询、编辑、浏览和管理工具。RazorSQLformac特别版可以帮你管理多个数据库,支持主流的30多种数据库,包括Ca...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
推荐7个模板代码和其他游戏源码下载的网址
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
-
- Mysql和Oracle实现序列自增(oracle创建序列的sql)
- 关于Oracle数据库12c 新特性总结(oracle数据库19c与12c)
- MySQL CREATE TABLE 简单设计模板交流
- mysql学习9:创建数据库(mysql5.5创建数据库)
- MySQL面试题-CREATE TABLE AS 与CREATE TABLE LIKE的区别
- Nike Dunk High Volt 和 Bright Spruce 预计将于 12 月推出
- 美国多功能舰载雷达及美国海军舰载多功能雷达系统技术介绍
- 汽车音响怎么玩,安装技术知识(汽车音响怎么玩,安装技术知识视频)
- 【推荐】ProAc Response系列扬声器逐个看
- #本站首晒# 漂洋过海来看你 — BLACK&DECKER 百得 BDH2000L无绳吸尘器 开箱
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)