【Java】 基础篇 -- 字符 char

char 在 Java 中是个很底层的东西了,比如 String 、StringBuilder 的底层就是它,但是在我们平时的工作中呢,很少使用他,不过既然是底层,今天我们大家就来一起研究下这 “哥们”。


char 用来表示 ==1 个字符== 。也就是说,如果你写 2个字符,那么这里是会报错的。如下:

// 这种编译报错 Too many characters in character literal
char c = '中国';

当然 char 也可以用来表示中文字符。在赋值时,我们经常这样表示:


 char c = '中';
        
 char c1 = 'H';

但是这里就会遇到一些面试上的坑了,比如使用字符类型进行算术运算和比较运算? 这是个什么鬼 A + B == ???

其实在 Java 内部进行字符处理时,采用的是 Unicode,(这里插一句 对 Unicode 和 UTF-X 的理解,Unicode 是一个包含世界各国字母的字符列表的编码。 Universal Multiple-Octet Coded Character Set”,简称 UCS, 俗称 “unicode “,就是每一个字母对应一个编码 ID,是一种映射关系,我们可以理解为 Unicode 是 一个标准,一个规则,而 UTF-X 则是一种具体的对 Unicode 的实现,UTF-X 是一种 针对 Unicode 的可变长度字符编码,也是一种前缀码,是一种编码格式。它可以用来表 示Unicode标准中的任何字符,而且 UTF-8 是兼容 ASCII 的。UTF-8 是 Unicode 的 实现方式之一。)

char 本质上是一个固定占用 2 个字节的无符号正整数,对应 Unicode, 也就是说 上面 的 李, H 都分别对应一个 正整数,char 只能表示 Unicode 编号在 65 536 以内的字符。因为一个字节 只能表示 256 个符号,2 个字节就是 256 x 256 = 65536 个符号。那么如果超出范围该咋表示呢,用 2 个char!!!


既然了解完了 Unicode,那么每个字符都可以用一个 对应的 编码ID 表示,也就是 一个正整数。既然是数字了,自然可以进行算术运算和比较运算。

char 的 二进制转换

下面我们就以 Integer 的转换二进制函数 toBinaryString 为例,说明一下 char 字节在 Java 中如何转换二进制的。

    public static void main(String[] args) {
        char c = '中';
        System.out.println(Integer.toBinaryString(c));
       // 二进制为:  100111000101101
    }

我们给 char 赋值一个 中文 字节 中,然后求出它的 二进制。

Integer 的 toBinaryString 方法:

    /**
     *   返回 输入参数 i 的 二进制字符串
     */
    public static String toBinaryString(int i) {
        return toUnsignedString0(i, 1);
    }

这里调用了 toUnsignedString0, 如下


   /**
     * Convert the integer to an unsigned number.
     * 转换一个 整型到一个无符号二进制数字
     */
    private static String toUnsignedString0(int val, int shift) {
        // 这里断言忽略
        // assert shift > 0 && shift <=5 : "Illegal shift value";
        // Integer.numberOfLeadingZeros 返回无符号整型的最高非零位前面的0的个数,包括符号位在内
        // 比如 Integer.numberOfLeadingZeros(10) 结果是 28
        // Integer.SIZE 为 32
        int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
        int chars = Math.max(((mag + (shift - 1)) / shift), 1);
        char[] buf = new char[chars];

        // 这里是整个方法的核心,整数转换二进制,然后更新 char 的缓冲
        formatUnsignedInt(val, shift, buf, 0, chars);

        // Use special constructor which takes over "buf".
        return new String(buf, true);
    }

核心转换函数 formatUnsignedInt 如下:

   /**
     * 格式化到字符缓冲区
     * @param val 被格式化的数
     * @param shift 格式化的类型 (4 代表16进制, 3 代表8进制, 1 代表二进制)
     * @param buf 待写入的字符缓冲区
     * @param offset 字符开始的位置
     * @param len 要写的字符数
     * @return the lowest character  location used
     */
   static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
        int charPos = len;
        int radix = 1 << shift;
        int mask = radix - 1;
        do {
            // 二进制的 & 运算,求出下标,然后获取 digits 中对应的值,写入 buf 缓冲区
            // final static char[] digits = {
            //               '0' , '1' , '2' , '3' , '4' , '5' ,
            //               '6' , '7' , '8' , '9' , 'a' , 'b' ,
            //               'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
            //               'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
            //               'o' , 'p' , 'q' , 'r' , 's' , 't' ,
            //               'u' , 'v' , 'w' , 'x' , 'y' , 'z'
    }
            buf[offset + --charPos] = Integer.digits[val & mask];
            // 无符号右移
            val >>>= shift;
        } while (val != 0 && charPos > 0);
        return charPos;
    }

通过上面的代码可以看出,Integer 内部维护了一个 char 数组,我们的普通字符转换 二进制的时候,都是求出 digits 某个下标的值,然后写到缓冲区,以 String 的形式返回给用户的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容

  • 字符是用户可以读写的最小单位。计算机所能支持的字符组成的集合,就叫做字符集。字符集通常以二维表的形式存在。二维表的...
    刘惜有阅读 8,098评论 2 14
  • 网站乱码问题我们会经常碰到,大多见于非英文的中文字符或其他字符乱码,而且,这类问题常常是因为编码方式问题,主要原因...
    波段顶底阅读 2,842评论 1 9
  • 每一个不经世事的女生都曾是天使 只是后来误落凡间,经世俗打磨成为了普罗大众的人。 网上铺天盖地...
    做一个庸俗的人阅读 502评论 5 8
  • 当初能做成 现今如何静如此 再也没有为你准备好的资料,你学完就基本全懂了 有的是不断有新挑战,住房,独自生活,工作...
    Zgmdada阅读 159评论 0 0
  • 套期保值,那只是投机的一种借口而已。 直到飞机平稳的落地北京机场,肖遥还一直觉得自己好像仍旧是在做梦之中。从临时决...
    luozi阅读 199评论 0 0