疑问1:java char范围0 | 您所在的位置:网站首页 › 字符串200能存多少汉字 › 疑问1:java char范围0 |
2019独角兽企业重金招聘Python工程师标准>>> 怀疑首先起于这里:我用 char存储单个的汉字,但是突然想到,如何char的范围仅有0-65535,如何表示所有的汉字(汉字博大精深,已远超65535个) 于是我打开eclipse试验char char ch = (char) 65535; System.out.println(ch);编译器不报错,打印了空(什么都没有),估计此处无字符,可以理解。 接下来,我修改为65536 char ch = (char) 65536; System.out.println(ch);居然编译不报错,我有点晕了,不是最大65535么,怎么大于也行? 接下来,我找到一个有汉字的84426 char ch = (char) 84426; System.out.println(ch);这里打印出了“䧊”,why?一头雾水,java官方说明文档也是指定其是2个byte,16位的无符号值,也即0-65535,why此处84426都可以,而且打印出了“䧊” 后来我又增加ch的值,想其难道是4个字节,直到2^31-1=2147483647时,不报错,加1时2147483648,编译不通过了,提示如下: char ch = (char) 2147483648;//The literal 2147483648 of type int is out of range System.out.println(ch);注意里面的提示The literal 2147483648 of type int is out of range,我才注意到后面的值其实是int的范围,所以编译不报错,同理long类型的更大,见 char ch = (char) 0xFFFFFFFFFFFFFFFFL;//0x表示16进制,后面的L标明为long类型所以编译不报错,指的是未超过后面类型的范围,所以不报错。 那么既然这么大,char范围0-65535那么小,是否有转换规则,是的,见下面 也就是大于65535的int值赋予char时,其会自动mod 65536(此处只针对大于,小于的话就不对了,见下),得出65535范围内的一个unicode int i = 18890 + 65536; //大于65535即mod,此处加了好几个65535,其还是代表18890 //int i = 18890 + 65536 + 65536 + 65536; //int i = 18890 - 65536 - 65536; char c = (char)i; System.out.println(c); //mod针对大于65535的还好使,但是其代表的是这个意思 System.out.println(i % 65536); //Integer.valueOf()能得到其代表的unicode值的大小,十进制int表示 System.out.println(Integer.valueOf(c)); char d = '䧊'; int n = (int)d; System.out.println(n);由上可见,其实“䧊”字的unicode码是18890,而非84426,并且其范围超过0-65535的范围,如果强制转换(char c = (char)i;)java会根据规则自动转换到0-65535区间中的一个。 到这里估计也就明白了,是自己写错了,下面这种方式肯定会提示编译错误的 char ch = 65536;// Type mismatch: cannot convert from int to char也即char的范围的确是0-65535。其实char单引号的写法( char ch = '䧊';),只是为了方便记忆和书写,它还是会转为数字码的形式,也即unicode码存储。 那到了这里 疑问还在,那就是65535的范围如何存储那么多的汉字? 答案是其存不了那么多,最多只能是65535,因为在此范围之外的都会转换到此范围里 而且我试了找到65535之外的汉字(用此工具查看UniToy)来试验,可是始终无法打出这些汉字,遂放弃了 大于65535的汉字,截取一部分 还有点疑问:看下面 public class Test { public static void main(String[] args) { String str= "中"; char x ='中'; byte[] bytes=null; byte[] bytes1=null; byte[] bytes2=null; try { bytes = str.getBytes("gbk"); bytes1 = str.getBytes("utf-8"); bytes2 = charToByte(x); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } System.out.println("bytes 大小:"+bytes.length); System.out.println("bytes1大小:"+bytes1.length); System.out.println("char转换为byte数组大小:"+bytes2.length); System.out.println("byte数组的两个值,其实unicode值的两个字节拆分到数组里了:"+bytes2[0]+"-"+bytes2[1]); } // 如“中”的unicode值为Integer.valueOf(x)=20013 // 二进制为0100 1110 0010 1101 // 拆分出来即为b[0]=0100 1110 b[1]=0010 1101 public static byte[] charToByte(char c) { byte[] b = new byte[2]; b[0] = (byte) ((c & 0xFF00) >> 8); b[1] = (byte) (c & 0xFF); return b; } }输出: gbk byte数组大小:2 utf8 byte数组大小:3 char转换为byte数组大小:2 byte数组的两个值,其实unicode值的两个字节拆分到数组里了:78-45 java是用unicode来表示字符,"中"这个中文字符的unicode就是2个字节。 String.getBytes(encoding)方法仅是获取指定编码的byte数组表示,而非java char存储时会占3个字节,只是utf8编码时该占几个字节 通常gbk/gb2312是2个字节,utf-8是3个字节。 如果不指定encoding则取系统默认的encoding。 ----------------------------------------------------------------------------------------------------------- 另UTF-8,GBK等这里没涉及,他们只是编解码规则,按一定规则编解码,再和其对应的字符图案对应起来。 其实简单来说UTF-8就是unicode码如何转换为字符来显示的,其有一定的转换规则,具体见http://my.oschina.net/u/914655/blog/318738处第11项。 另目前汉字范围及与unicode如何对应 GB2312有6763个汉字,GBK有21003个汉字,GB18030-2000有27533个汉字,GB18030-2005有70244个汉字。 Unicode 5.0中,如果不算兼容区,目前有70217个汉字。让我们比较一下Unicode的70217汉字和GB18030-2005中的70244汉字: GB18030-2005 Unicode 5.0对应的Unicode编码CJK统一汉字的20902汉字CJK统一汉字的20902汉字0x4E00-0x9FA5CJK统一汉字扩充A的6582汉字CJK统一汉字扩充A的6582汉字0x3400-0x4DB5CJK统一汉字扩充B的42711汉字CJK统一汉字扩充B的42711汉字0x20000-0x2A6D6CJK部首补充区的14个部首未计入2E81, 2E84, 2E88, 2E8B, 2E8C, 2E97, 2EA7, 2EAA, 2EAE, 2EB3, 2EB6, 2EB7, 2EBB, 2ECACJK兼容汉字区的21个汉字未计入F92C, F979, F995, F9E7, F9F1, FA0C, FA0D, FA0E, FA0F, FA11, FA13, FA14, FA18, FA1F, FA20, FA21, FA23, FA24, FA27, FA28, FA29![]() |
CopyRight 2018-2019 实验室设备网 版权所有 |