在平常工作中使用到char和byte的场景不多,但是如果项目中使用到IO流操作时,则必定会涉及到这两个类型,下面让我们一起来回顾一下这两个类型吧。
char和byte的对比
byte
byte 字节,数据存储容量1byte,byte作为基本数据类型表示的也是一个存储范围上的概念,有别于int、long等专门存数字的类型,这种类型的大小就是1byte,而int是4byte。
存数字的话就是1byte=8位,2^8=256 即-128-127。字符的话包括字母和汉字,一个字母是1byte,一个汉字2byte。也就是可以用byte变量去存储一个英文字符,但是却存不下一个中文汉字,因为一个汉字占2byte。
总结,byte是java中的一个基本数据类型,这个数据类型的长度是1byte,此byte就是彼byte,即是基本数据类型也是存储空间的基本计量单位。
char
char是Java中的保留字,与别的语言不同的是,char在Java中是16位的,因为Java用的是Unicode。不过8位的ASCII码包含在Unicode中,是从0~127的。
Java中使用Unicode的原因是,Java的Applet允许全世界范围内运行,那它就需要一种可以表述人类所有语言的字符编码。Unicode。
char本质上是一个固定占用两个字节的无符号正整数,这个正整数对应于Unicode编号,用于表示那个Unicode编号对应的字符。
由于固定占用两个字节,char只能表示Unicode编号在65536以内的字符,而不能表示超出范围的字符。
Unicode和UTF-8的对比
Unicode
需要注意的是,Unicode只是一个符号集,它只规定了符号的二进制代码,却没有规定这个二进制代码应该如何存储。
比如,汉字"严"的unicode是十六进制数4E25,转换成二进制数足足有15位(100111000100101),也就是说这个符号的表示至少需要2个字节。表示其他更大的符号,可能需要3个字节或者4个字节,甚至更多。
这里就有两个严重的问题,第一个问题是,如何才能区别Unicode和ASCII?计算机怎么知道三个字节表示一个符号,而不是分别表示三个符号呢?第二个问题是,我们已经知道,英文字母只用一个字节表示就够了,如果Unicode统一规定,每个符号用三个或四个字节表示,那么每个英文字母前都必然有二到三个字节是0,这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍,这是无法接受的。
它们造成的结果是:1)出现了Unicode的多种存储方式,也就是说有许多种不同的二进制格式,可以用来表示Unicode。2)Unicode在很长一段时间内无法推广,直到互联网的出现。
UTF-8
互联网的普及,强烈要求出现一种统一的编码方式。UTF-8就是在互联网上使用最广的一种Unicode的实现方式。其他实现方式还包括UTF-16(字符用两个字节或四个字节表示)和UTF-32(字符用四个字节表示),不过在互联网上基本不用。重复一遍,这里的关系是,UTF-8是Unicode的实现方式之一。
以utf8为例,utf8是一个变长编码标准,可以以1~4个字节表示一个字符,而中文占3个字节,ascII字符占1个字节。
为什么我们在java里面可以用一个char来表示一个中文呢?
因为java是以unicode作为编码方式的。unicode是一个定长的编码标准,每个字符都是2个字节,也就是1个char类型的空间。
在编译时会把utf8的中文字符转换成对应的unicode来进行传输运算。
示例代码
package com.lingyejun.io; import java.io.UnsupportedEncodingException; /** * Created by Lingye on 2018/9/28 14:34 */ public class ChineseCharCode { public static void main(String[] args) { String str = "中"; char c = '中'; // java使用unicode编码,一个字符占两个字节 System.out.println("char字符 中 二进制"+Integer.toBinaryString(c)); try { // UTF-8是Unicode的实现方式之一 System.out.println(str.getBytes("UTF-8").length); // UTF-16也是Unicode的实现方式之一,但使用较少 System.out.println(str.getBytes("UTF-16").length); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } }
输出结果及总结
- 因为Java是以unicode作为编码方式的。unicode是一个定长的编码标准,每个字符都是2个字节,也就是1个char类型的空间。
- Java在编译时会把utf8的中文字符转换成对应的unicode来进行传输运算。
- 在Java中,基本类型char,固定占两个字节,char本质上就是一个无符号的正整数,我们可以使用Integer.toBinaryString(c))将其打印出来。
- UTF-8采用的是变长字节编码的方式进行编码,一个汉字可以以1~4个字节表示一个字符,而中文占3个字节,ascII字符占1个字节。
参考文章:https://www.zhihu.com/question/23374078