《Java编程的逻辑》精读二(数据类型,字符编码)

最近在阅读《Java编程的逻辑》一书,受益良多,在此对作者(马俊昌)万分的感谢。

计算机是一个机器,只能处理二进制数据,比如0100 1101。
但直接使用二进制进行编程开发,非常的不友好,所以有了各种高级开发语言,如 CC++C#JavaPHP等。
为了更好的操作二进制数据,高级开发语言大多引入了数据类型的概念,使用不同的类型来表示数据。

基本数据类型

对于 Java 语言来讲,有如下基本数据类型:

1、整数类型

byte

占1个字节,8位二进制,第1位是符号位,取值范围为:-27(即1000 0000) ~ 27-1(即0111 1111)。

byte b = 23;
short

占2个字节,16位二进制,第1位是符号位,取值范围为:-215(即1000 0000 0000 0000) ~ 215-1(即0111 1111 1111 1111)。

short s = 3333;
int

占4个字节,32位二进制,第1位是符号位,取值范围为:-231(即1000 0000 0000 0000 0000 0000 0000 0000) ~ 231-1(即0111 1111 1111 1111 1111 1111 1111 1111)。

int i = 9999;
long

占8个字节,64位二进制,第1位是符号位,取值范围为:-263 ~ 263-1。
整数值默认为int类型,给long类型变量赋值时需要在后面加小写字母 l 或大写字母 L,防止值超出了int的取值范围。

long l = 32323L;

2、浮点数类型

浮点数,即数学中的“小数”。
因为在计算机中表示小数的点不是固定的,而是浮动的,所以被称为“浮点数”。

浮点数在计算机中采用类似十进制的科学计数法来表示的,即m×2n,其中m称为“尾数”,n称为“指数”。
计算机中保存的小数,即保存的m和n。

由此可见,计算机只能精确的表示可以表述为2的几次方的小数(比如1×2-1:0.5、3×2-2:0.75、6×2-3:0.75),其他小数则无法精确的表示(类比一下十进制中的小数只能精确表示10的几次方的小数)。

float

占4个字节,32位二进制,第1位是符号位,中间23位保存尾数,最后8位保存指数。
浮点数的值默认为double类型,给float类型变量赋值时需要在后面加小写字母 f 或大写字母 F

float f = 2.11f;
double

占8个字节,64位二进制,第1位是符号位,中间52位保存尾数,最后11位保存指数。

double d = 2.11;

3、boolean类型

用boolean表示,值只有true或false两种。

boolean b = true;

boolean类型的大小没有明确定义。
下面参考Java中boolean类型到底占用多少个字节?
单独的boolean类型编译后会用int代替,boolean值占用4个字节(32位二进制)。
boolean类型数组会被编译为byte数组,每个boolean值占用1个字节(8位二进制)。
使用int代替boolean,而不用byte或short的原因是,对于当下32位的处理器(CPU)来说,一次处理数据是32位(这里不是指的是32/64位系统,而是指CPU硬件层面),32 位 CPU 使用 4 个字节是最为节省的,哪怕你是 1 个 bit 他也是占用 4 个字节。因为 CPU 寻址系统只能 32 位 32 位地寻址,具有高效存取的特点。

4、字符(char)类型

用char表示,值是一个字符,中文或英文字符都行。
使用单引号把字符括起来。

char c1 = 'a';
char c2 = '我';

Java内部处理字符时,使用的是Unicode编码,具体编码格式为 UTF-16BE(UTF-16大端表示)。
所以字符类型本质上也是一个整数,占2个字节或4个字节,下面有具体说明。

Unicode编码

Unicode编码为世界上所有字符都分配了一个唯一的数字编号,范围从0x000000~0x10FFFF,前缀使用U+。
Unicode编码并没有规定这个编号怎么和二进制对应,下面是几个主要方案:

  • UTF-32
    这个简单,直接使用数字编号的二进制表示,占4个字节,32位二进制。
    缺点是浪费空间,实际采用比较少。
    这里需要注意字节的排列顺序(字节序):
    大端(Big Endian,BE)
    对应编码:UTF-32BE
    第一个字节是二进制表示中的最高位,最后一个字节是二进制表示中的最低位。
    小端(Little Endian,LE)
    对应编码:UTF-32LE
    第一个字节是二进制表示中的最低位,最后一个字节是二进制表示中的最高位。

  • UTF-16
    使用变长字节表示:
    常用字符集
    在U+0000~U+FFFF之间,即65536个数字之内,用2个字节可表示(16位二进制)。
    U+D800~U+DBFF之间的编号其实没有定义。
    增补字符集
    在U+10000~U+10FFFF之间,用4个字节(32位二进制)表示。
    前两个字节叫高代理项,范围是U+D800~U+DBFF,后两个字节叫低代理项,范围是U+DC00~U+DFFF。
    数字编号与这个二进制之间有一个转换算法。

    区分是2个字节还是4个字节,就看前两个字节的编号范围。
    如果在U+D800~U+DBFF范围内,就是4个字节。
    这里也有字节序的问题,有 UTF-16BEUTF-16LE 两种编码。
    UTF-16常用于系统内部编码,比UTF-32节省空间,但也至少需要2个字节表示,对于美国和西欧国家来说还是有点浪费。

  • UTF-8
    也使用变长字节表示,占用1~4个字节,每个字符的字节个数与字符在Unicode中的编号大小有关。
    对于编号小于128的字符,即ASCII码表中的字符,占用1个字节(8位二进制),最高位固定为0,剩余7位表示字符。
    对于编号大于128的字符,最高位字节(即BE表示中的第一个字节)中有几个连续的1,就表示该字符一共有几个字节(包括最高位字节,最高字节后面的字节都是10开头)。
    UTF-8是兼容ASCII码的,对于大部分中文,一个中文字符需要用3个字节表示(即1110 xxxx 10xx xxxx 10xx xxxx,其中x填补字符的Unicode编号的二进制形式(去掉最高位的0))。

非Unicode编码
  • ASCII(American Standard Code for Information Interchange)
    美国用,占用1个字节(8位二进制),最高位固定为0,剩余7位表示字符。
    数字32~126对应可打印字符,如大小写字母,各种特殊符号(!@#%^&*-+./)等。
    数字0~31和127表示控制字符,如空格,换行符,制表符等。
  • ISO 8859-1 / Latin-1
    西欧用,兼容ASCII,占用1个字节(8位二进制),最高位固定为1,剩余7位表示字符。0~127与ASCII一样,128~255有其他含义。
  • Windows-1252(现在主流使用)
    西欧用,兼容ASCII,与ISO 8859-1基本一样,区别在于数字128~159,增加了欧元等特殊字符。
  • GB2312
    中国用,主要针对简体中文(约7000个)和个别罕见字和繁体字。
    兼容ASCII。
    占用2个字节(16位二进制),最高位固定为1。
    如果最高位是0,按ASCII解析。
    高位字节范围0xA1~0xF7,低位字节范围0xA1~0xFE。
  • GBK
    中国用,向下兼容GB2312,增加了更多的简体字和繁体字,共约约21000个字符。
    兼容ASCII。
    占用2个字节(16位二进制),最高位固定为1。
    高位字节范围0x81~0xFE,低位字节范围0x40~0x7E和0x80~0xFE。
    低位字节从0x40开始,即低位字节最高位可能是0。
    使用高位字节(第一个字节)的最高位是否是1,来区分低位字节是否是汉字的一部分。
    如果第一个字节最高位是0,第一个字节按ASCII解析,然后再解析后面的字节是ASCII还是汉字。
    如果第一个字节最高位是1,则把第一个字节和第二个字节一起解析为一个汉字,解析完,跳到第三个字节解析。
  • GB18030
    中国用,向下兼容GBK、GB2312,增加了少数民族字符,中日韩统一字符,共约76000个字符。
    使用变长字节。
    兼容ASCII。
    对于2字节编码,GBK一摸一样,占用2个字节(16位二进制),高位字节范围0x81~0xFE,低位字节范围0x40~0x7E和0x80~0xFE。
    对于4字节编码,第一个字节范围为0x81~0xFE,第二个字节范围为0x30~0x39,第三个字节范围为0x81~0xFE,第一个字节范围为0x30~0x39。
    解析二进制,通过第二个字节的范围来确定是4字节编码还是2字节编码,因为2字节编码中的第二个字节比4字节编码中的第二个字节大。
  • Big5
    香港、台湾用,针对繁体中文的。
    兼容ASCII。
    占用2个字节(16位二进制),最高位固定为1。
    高位字节范围0x81~0xFE,低位字节范围0x40~0x7E和0xA1~0xFE。

⚠️ 字符乱码的问题,都是读取字符时用的编码与写字符时用的编码不一致造成的。

数组类型

数组中的元素是连续存放的。
数组的长度一旦确定,就不可更改。
基本数据类型的变量,在内存中只有一个对应的内存空间,直接存储变量的值。
而数组类型的变量,在内存中有两个对应的内存空间:一个存放该数组变量的值的起始位置,一个存放该数组变量的值的内容。
类似数组类型存储方式的类型,一般也称为引用类型。

在Java中,许多复杂的类型,都是使用基本数据类型和数组类型组合而成,比如:
String/StringBuilder/StringBuffer:内部使用char数组,所有字符串的操作都是基于该数组的。
ArrayList/ArrayDeque:内部使用泛型数组,所有Array操作都是基于该数组的。
Date:内部使用long值表示距离纪元时的毫秒数,所有时间操作都是基于该毫秒数的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容