Java中如何存储汉字

Java中如何存储汉字

因为笔者了解有限,文中难免会出现一些错误,如有发现,望指出,谢谢。

依稀记得当初刷面试题时,有道题是这样的

char 型变量中能不能存贮一个中文汉字,为什么?
答:char类型可以存储一个中文汉字,因为Java中使用的编码是Unicode(不选择任何特定的编码,直接使用字符在字符集中的编号,这是统一的唯一方法),一个char类型占2个字节(16比特),所以放一个中文是没问题的。

记得当时也很疑惑,只是学疏才浅,加上忙于找工作,也没多在意。直到无意间又遇到了这个问题,便一步一步踏上了寻找之旅。
首先,汉字的存储和字符集有关,字符集不同,存储汉字所用的字节也不同。
如上题所述,Java中使用的编码是Unicode,但是Unicode 是「字符集」(为每一个「字符」分配一个唯一的 ID),不负责具体的编码规则(将「码位」转换为字节序列的规则)。那么在汉字Java中的编码规则是什么呢?

char

原本想从char找起,奈何char是基本类型,没有办法查看类定义信息,然后就想到了包装类Character,果不其然在其中找到了一些信息。在这里插入图片描述
由此可见,Java采用UTF-16编码,但是我了解到汉字(Unicode常见的汉字编码范围0x4E00-0x9FA5)在UTF-16占2个字节(对于 Unicode 码小于 0x10000 的字符, 使用 2 个字节存储,并且是直接存储 Unicode 码),char有2个字节,可以放下。UTF-16 用两个字节表示一个字符,那么用两个字节表示必然存在字节序的问题(Byte Order Mark(BOM)),即大端小端的问题。UTF-16根据BOM分为UTF-16BE(最低地址存放高位字节,编码前会放置FEFF)和UTF-16LE(最高地址存放高位字节,编码前会放置FFFE),那么Java中采用的是UTF-16BE还是UTF-16LE?由于不想继续找下去,所以就直接用现象去推出结论,测试代码如下:

 public static void main(String[] args) {
        char ch = '我';
}

在Debug模式下结果如下:
测试
发现’我’在char中存储的是25105,然后在编码中发现’我’的编码如下:
在这里插入图片描述
将十进制的25105('我’在char中存储的值)转化为十六进制,结果为6211,对比上述编码后四位,最终确定,Java采用的是UTF-16BE。

String

说起char就不得不说起String,因此我就测试了String,String结构如下:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    ...
    @Stable
    private final byte[] value;
    ...
}

由此可见真正存放数据的是byte[]数组(被final修饰,这是String不可变的原因),一个byte占一个字节,那么猜想’我’存放在String中是byte[2],果然,结果符合设想,然后查看值,
在这里插入图片描述
那么[17,98]到底代表什么含义呢,首先,我想到了转换为十六进制,但是两个值没办法直接转换,所以就先转化为了二进制,因为计算机存储的是补码(byte占一个字节,为8位),转换为补码为[00010001, 01100010],然后根据BE中最低地址存放高位字节,从后往前拼接,[00010001, 01100010]–>0110001000010001–>110001000010001。将二进制110001000010001转换为十六进制为6211,和上述存储结果一致。
至此,得出结论,Java中汉字的编码规则为UTF-16BE。

  • 14
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值