首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java 基础 -- 基础字符 char

Java 基础 -- 基础字符 char

作者头像
haoming1100
发布2019-04-18 14:46:27
6080
发布2019-04-18 14:46:27
举报
文章被收录于专栏:步履前行步履前行

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 的形式返回给用户的。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-04-08 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • char 的 二进制转换
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档