这是数据类型专题最后一个部分,包含了最后一个基本类型char类型和类型转换的知识。像这样的专题内容,小猿会在期中考试之前整理成pdf格式放送给各位老粉的,现在关注你也是老粉!
char 类型
char类型是字符类型。占16 bits 空间,取值范围为[0,65535],char类型很简单,有趣的是char类型背后的编码。Java的char类型采用的是Unicode
编码。
可以通过以下方式查看某个字符的Unicode编码(比如这两天经常困扰同学们的中文引号和括号),Unicode
用四位十六进制数字表示:
charc1=')'; charc2='“'; System.out.format("%x",(int)c1); System.out.format("%x",(int)c2); }/*output: ff09 201c */publicstaticvoidmain(String[]args){
也可以通过编码获得字符(需要通过\u
进行转义):
charc1='\u0056'; charc2='\u0057'; System.out.println(c1+""+c2) }/*output: VM */publicstaticvoidmain(String[]args){
看到这里,小猿相信同学就能明白char类型为什么本质上还是一个整数类型了。而多个char类型连续的拼在一起,就是String
类型
(选读)编码
众所周知,计算机只能储存二进制数字,想要让计算机储存字符,必须制订一套将数字和字符一一对应的标准,在读出数字之后通过映射关系获得字符,这种标准就被称为编码 (character encoding standard)。编码的早期形态就是ASCII
(American Standard Code for Information Interchange) 。ASCII
标准中一个字符占据 8 bits 空间,理论上 ASCII 编码可以包含 255 个字符 ,足以编码大部分拉丁语系的语言,但是当计算机逐渐推广到全世界,哪怕只和繁星一般多的汉字相比,ASCII
编码可怜的容量就已经相形见绌了,更不要说日语,印度文等语言了。
为了解决拉丁语系外的语言的编码问题 “万国码” -Unicode
诞生了,Unicode的宗旨是将世界上的所有语言中的字符乃至数学符号进行编码。一单位Unicode
本身含有16个bits,在表示时使用4位16进制数字。单个Unicode
标准下的char类型称为单位(unit),而字符则被称为码点 (code point),由于编码进Unicode
的字符越来越多,[0,65535]的容量已经不够了,于是Unicode
就增加了两个单位表示一个码点的机制,这样,理论上Unicode
的容量就扩大了大概 倍,足以编码所有世界上现有的以及未来产生的字符了。
但是Unicode
追求的是大和全,其代价是成倍增长的储存空间占用,这给网络带来了很大的负担。于是基于Unicode,人们又发展出了各种UTF
(Unicode Transformation Format) 编码版本,其中最常用的当数UTF-8
编码,UTF-8
编码单个单元占据 8 bits,但是其采用一种变长编码的策略,这使得UTF-8
编码包含了大部分常用字符的同时具有很好的空间利用效率。同时,UTF-8
编码的前 8 bits 是兼容ASCII
编码的。
除了国际编码,各国也有本国语言专用的编码。GBK
系列就是基于ASCII
发展出来的专门编码汉字的编码,其在储存和传输汉字方面比UTF-8
更加实惠。
类型转换
我们讨论类型转换时,一般所指的是 8 种基本类型和String
类型一共9种类型间的相互转换。
安全的类型转换
类型转换 (casting) 的本质是改变数据在底层的储存方式,由于每种数据有其范围和精确度,从小范围,低精确度的数据类型转向大范围,高精确度的数据类型是安全的,8种基本数据类型的范围,精确度从小(低)到大(高)排名为 boolean,byte,short = char,int ,long float,double。这种安全的转换存在于8种基本类型之间,而且往往是自动(隐式)完成的:
inti='a';//char转为int intc1='\u0056';//char转为int longl=38912;//int转为long doubled=232l;//long转为doubledoubled=1.0/8;//int转为double
以上这些语句出现在代码中时,不会有任何警告和错误。
强制类型转换
从大范围,高精确度的数据类型转向小范围,低精确度的数据类型是有风险的,因为这样的做法很可能会导致数据的丢失。
inti=1000000000000l;//error
这种语句在运行之前IDE
就会发出警告,强行运行的话会导致编译时期错误。
想要完成这种转型,必须使用强制类型转换,语法非常简单,就是在变量/字面量前加用一对括号包围的数据类型:
System.out.println(i); /*output: -727379968 */inti=(int)1000000000000l
可以看到,以上的这个强制转型产生了非常严重的精度损失。强制转型有很大的风险,没有充足的把握不要使用强制转型,更不要为了能通过编译使用强制转型!
基本类型和String
类型的转换
在以往的推文中,小猿提到过:
从基本类型转到String
为了使Java面向对象的版图完整,Java官方库提供了包装类(wrapper class),8个基本类型有8个对应的包装类:Integer Byte Long Short Character Double Float Boolean
,这8个类从属于java.lang
包,不需要手动import
(java.lang
包在所有的java源码中被隐式地引用)。在Java中,每个对象都有用toString()
方法,每个包装类的toString()
方法有两种调用方式:
Strings1=Integer.toString(i); Strings2=i.toString();Integeri=100;
其他的包装类类推即可。当然,也可以使用String.valueOf()
方法。
从String到基本类型
这个情况在处理输入时比较常见,比如用户输入了一串数字字符串,我么需要将其转换成数字。强大的Java官方库提供了现成的方法:
inti=Integer.parseInt("12378");
这样的现成的函数在java中基本上每个基本类型都有,小猿就留给同学们自己探索了。如果在c语言中,这个问题就比较痛苦了,需要用循环一位一位的处理,可见官方库对一门语言易用程度的影响。
有任何Java学习相关的问题,或者找到了文章中的错误,可以在公众号后台给小猿留言哦。