- 一、注释、标识符、关键字
- 1.1 注释
- 1.2 标识符
- 1.3 关键字
- 二、数据类型
- 2.1 强弱类型语言
- 2.1.1 强类型语言
- 2.1.2 弱类型语言
- 2.2 动静态语言
- 2.2.1 动态性语言
- 2.2.2 静态性语言
- 2.3 Java 数据类型
- 2.3.1 进制
- 1. 进制三要素
- 2. 进制转换
- (1)二进制转换成其他进制
- (2)八进制转换成其他进制
- (3)十进制转换成其他进制
- (4)十六进制转换成其他进制
- 2.3.2 原码、反码和补码
- 1. 用法
- 2. 为什么要使用原码、反码和补码?
- 2.3.3 基本数据类型
- 1. 数值类型(有符号数值需要保留一个二进制位存储符号)
- (1)整数类型(1 个字节(byte)为 8 个二进制位(bit))
- (2)浮点类型
- 详解移位存储
- (3)字符类型
- 2. boolean 类型
- 2.3.2 引用数据类型(后续详解)
- 平时我们编写代码,在代码量比较少的时候,我们还可以看懂自己写的,但是当项目结构一旦复杂起来,我们就需要用到注释了。
- 注释并不会被执行,是我们写代码的人看的。
- 书写注释是一个非常好的习惯。
- Java 中的注释有三种:
- 单行注释:// 单行注释只能注释一行
- 多行注释:可以注释一段文字
- 文档注释:后续 JavaDoc 中详细讲解。
- Java语言中的变量、常量、函数、类、语句块等组成部分都需要名字,我们将这些名字统统称为 Java 标识符。
- Java 标识符由数字、字母(A-Z 或 a-z)、下划线(_)和美元符号($)或人民币符号(¥)组成。
- Java 标识符是区分大小写的,并且要求首位不能是数字。
- Java 关键字和保留字不能用作 Java 标识符。
- 可以使用中文命名,但是一般不建议这样去使用,也不建议使用拼音。
- 合法的标识符:myName, My_name, Points, $points, _sys_ta, OK, _23b, _3_
非法的标识符:#name, 25name, class, &time, if - 命名约定:
- 类和接口名:每个单词的首字母大写,含有大小写。例:MyClass, HelloWorld, Time 等。
- 方法名:第一个单词的首字母小写,其余单词首字母大写,含有大小写,尽量少用下划线。例:myName, setTime 等。这种命名方法叫做驼峰式命名。
- 常量名:基本数据类型常量名的全部字母都大写,单词与单词之间使用下划线分隔。对象常量可大小混写。例:SIZE_NAME。
- 变量名:可大小写混写,首字符小写,字间分隔符用字的首字母大写。不用下划线,少用美元符号。给变量命名是尽量做到见名知义。
quad Java 关键字,有时又叫保留字,是对 Java 编译器有特殊含义的字符串,是编译器和程序员的一个约定,程序员利用关键字来告诉编译器其声明的变量类型、类、方法特性等信息。Java 中一共有 53 53 53 个关键字。
- 访问控制( 3 3 3 个):private, protected, public;
- 类,方法和变量修饰符( 13 13 13 个):abstract, class, extends, final, implements, interface, native, new, static, strictfp, synchronized, transient, volatile;
- 程序控制( 12 12 12 个):break, continue, return, do, while, if, else, for, instanceof, switch, case, default;
- 异常处理( 6 6 6 个):assert, try, catch, finally, throw, throws;
- 包相关( 2 2 2 个):import, package;
- 基本类型( 12 12 12 个):boolean, byte, char, double, float, int, long, short, null, true, false, enum;
- 变量引用( 3 3 3 个):super, this, void;
- 保留字( 2 2 2 个):goto, const。
quad 强类型语言和弱类型语言其判断的根本为是否隐形进行语言类型转变。
2.1.1 强类型语言quad 强类型是针对类型检查的严格程度而言的,它指任何变量在使用的时候必须要指定这个变量的类型,而且在程序的运行过程中这个变量只能存储这个类型的数据。因此,对于强类型语言,一个变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转换。常用的强类型语言有 Java、.net、C#、Apex和 Python 等。
2.1.2 弱类型语言quad 弱类型语言是一种数据类型可以被忽略的语言,它与强类型定义语言相反,一个变量可以赋不同数据类型的值,当某一个变量被定义数据类型,该变量可以根据环境变化自动进行转换,不需要经过强制转换。常用的弱类型语言有 VB, PHP, Javascript 等。
2.2 动静态语言 2.2.1 动态性语言quad 动态性语言是指在运行期间才去做数据类型检查的语言,也就是说动态类型语言编程时,永远不用给任何变量指定数据类型,该语言会在第一次赋值给变量时,在内部将数据类型记录下来。Python 和 Ruby 就是一种典型的动态类型语言。
2.2.2 静态性语言quad 静态性语言是指编译期间做数据类型检查的语言,即写程序时要声明所有变量的数据类型。使用数据之前,必须先声明数据类型(int, float, double 等)。相当于在使用之前,首先要为它们分配好内存空间。C/C++ 是静态类型语言的典型代表。Java也是一种静态性语言。
2.3 Java 数据类型 2.3.1 进制
quad
在讲进制之前,我们先看一下数制的定义:用一组固定的数字和一套统一的规则来表示数目的方法称为数制。
quad
而数制有进位计数制与非进位计数制之分。非进位计数制的数码表示的数值大小与它在数中的位置无关,这里我们不作过多的介绍。进位计数制的数码所表示的数值大小则与它在数中所处的位置有关,常见的有二进制(前缀0b)、八进制(前缀0)、十进制、十六进制(前缀0x)。
- 数码:用来表示进制数的元素。例:二进制数的数码为:0,1;八进制数的数码为:0,1,2,3,4,5,6,7;十进制数的数码为:0,1,2,3,4,5,6,7,8,9;十六进制数的数码为:0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F。
- 基数:数码的个数。例:二进制数的基数为 2;八进制数的基数为 8;十进制数的基数为 10;十六进制数的基数为 16。
- 位权:数制中每一固定位置对应的单位值称为位权。例:十进制第 2 位的位权为 10( 1 0 1 10^{1} 101),第 3 位的位权为 100( 1 0 2 10^{2} 102);而二进制第 2 位的位权为 2( 2 1 2^{1} 21),第 3 位的位权为 4( 2 2 2^{2} 22)。由此可见,对于 n 进制数,整数部分第 i 位的位权为 n ( i − 1 ) pmb{n^{(i-1)}} n(i−1)n(i−1)n(i−1),而小数部分第 j 位的位权为 n − j pmb{n^{-j}} n−jn−jn−j。
那么我们可以说:每个数码所表示的十进制数值 = 该数码值 * 所处位置的位权。
例: 十进制数: ( 123.45 ) 10 = 1 × 1 0 2 + 2 × 1 0 1 + 3 × 1 0 0 + 4 × 1 0 − 1 + 5 × 1 0 − 2 (123.45)_{10}=1×10^2 + 2×10^1 + 3×10^0 + 4×10^{-1} + 5×10^{-2} (123.45)10=1×102+2×101+3×100+4×10−1+5×10−2
quadquad 二进制数: ( 1010 ) 2 = 1 × 2 3 + 0 × 2 2 + 1 × 2 1 + 0 × 2 0 = ( 10 ) 10 (1010)_2 =1×2^3 + 0×2^2 + 1×2^1 + 0×2^0=(10)_{10} (1010)2=1×23+0×22+1×21+0×20=(10)10
quadquad 八进制数: ( 327 ) 8 = 3 × 8 2 + 2 × 8 1 + 7 × 8 0 = ( 215 ) 10 (327)_8 =3×8^2+2×8^1+7×8^0=(215)_{10} (327)8=3×82+2×81+7×80=(215)10
quadquad 十六进制数: ( B A D ) 16 = 11 × 1 6 2 + 10 × 1 6 1 + 13 × 1 6 0 = ( 2989 ) 10 (BAD)_{16} =11×16^2 + 10×16^1 + 13×16^0=(2989)_{10} (BAD)16=11×162+10×161+13×160=(2989)10
2. 进制转换 (1)二进制转换成其他进制- 二进制(Binary)
⇒
pmb{Rightarrow}
⇒⇒⇒ 八进制(Octal)
quad
quad 因为每三位二进制数对应一位八进制数,所以,以小数点为界,整数位则将二进制数从右向左每 3 位一隔开,不足 3 位的在左边用 0 填充;小数位则将二进制数从左向右每 3 位一隔开,不足 3 位的在右边用 0 填充。
quad
例: 将二进制数 ( 10.10101 ) 2 (10.10101)_2 (10.10101)2 转化为八进制数。
( 10.10101 ) 2 = ( 010.101 010 ) 2 = ( 2.52 ) 8 quad(10.10101)_2 = (010.101 010)_2 = (2.52)_{8} (10.10101)2=(010.101 010)2=(2.52)8 - 二进制(Binary)
⇒
pmb{Rightarrow}
⇒⇒⇒ 十进制(Decimal)
quad
quad 以小数点为界,整数位从最后一 位(从右向左)开始算,依次列为第 0,1,2,...,n,然后将第 n 位的数(0 或 1)乘以 2 的 n-1 次方,然后相加即可得到整数位的十进制数;小数位则从左向右开始算,依次列为第 1,2,...,n,然后将第 n 位的数(0 或 1)乘以 2 的 -n 次方,然后相加即可得到小数位的十进制数(按权相加法)。
quad
例: 将二进制数 ( 10.10101 ) 2 (10.10101)_2 (10.10101)2 转化为十进制数。
( 10.10101 ) 2 = ( 1 × 2 1 + 0 × 2 0 + 1 × 2 − 1 + 0 × 2 − 2 + 1 × 2 − 3 + 0 × 2 − 4 + 1 × 2 − 5 ) 10 = ( 2 + 0 + 0.5 + 0 + 0.125 + 0 + 0.03125 ) 10 = ( 2.65625 ) 10 quad(10.10101)_2 = (1×2^1 + 0×2^0 + 1×2^{-1} + 0×2^{-2} + 1×2^{-3} + 0×2^{-4} + 1×2^{-5})_{10} = (2+0+0.5+0+0.125+0+0.03125)_{10} = (2.65625)_{10} (10.10101)2=(1×21+0×20+1×2−1+0×2−2+1×2−3+0×2−4+1×2−5)10=(2+0+0.5+0+0.125+0+0.03125)10=(2.65625)10 - 二进制(Binary)
⇒
pmb{Rightarrow}
⇒⇒⇒ 十六进制(Hex)
quad
quad 因为每四位二进制数对应一位十六进制数,所以,以小数点为界,整数位则将二进制数从右向左每 4 位一隔开,不足 4 位的在左边用 0 填充;小数位则将二进制数从左向右每 4 位一隔开,不足 4 位的在右边用 0 填充。
quad
例: 将二进制数 ( 10.10101 ) 2 (10.10101)_2 (10.10101)2 转化为十六进制数。
( 10.10101 ) 2 = ( 0010.1010 1000 ) 2 = ( 2. A 8 ) 16 quad(10.10101)_2 = (0010.1010 1000)_2 = (2.A8)_{16} (10.10101)2=(0010.1010 1000)2=(2.A8)16
- 八进制(Octal)
⇒
pmb{Rightarrow}
⇒⇒⇒ 二进制(Binary)
quad
quad 八进制转换成二进制与二进制转换成八进制相反。每一位八进制数对应三位二进制数。
quad
例: 将八进制数 ( 257.527 ) 8 (257.527)_8 (257.527)8转换为二进制
( 257.527 ) 8 = ( 10 101 111.101 010 111 ) 2 quad(257.527)_8 = (10 101 111.101 010 111)_2 (257.527)8=(10 101 111.101 010 111)2 - 八进制(Octal)
⇒
pmb{Rightarrow}
⇒⇒⇒ 十进制(Decimal)
quad
quad 将八进制每位上的数乘以八进制位权,然后将得出来的数再加在一起。
quad
例: 将八进制数 ( 257.527 ) 8 (257.527)_8 (257.527)8转换为十进制
( 257.527 ) 8 = 7 × 8 0 + 5 × 8 1 + 2 × 8 2 + 5 × 8 − 1 + 2 × 8 − 2 + 7 × 8 − 3 = ( 175.669921875 ) 10 quad(257.527)_8 = 7×8^0+5×8^1+2×8^2+5×8^{-1}+2×8^{-2}+7×8^{-3}=(175.669921875)_{10} (257.527)8=7×80+5×81+2×82+5×8−1+2×8−2+7×8−3=(175.669921875)10 - 八进制(Octal)
⇒
pmb{Rightarrow}
⇒⇒⇒ 十六进制(Hex)
quad
quad 将八进制转换为二进制,然后再将二进制转换为十六进制,小数点位置不变。
quad
例: 将八进制数 ( 257.527 ) 8 (257.527)_8 (257.527)8 转换为十六进制
quad 八进制数 ( 257.527 ) 8 (257.527)_8 (257.527)8 转换为二进制
( 257.527 ) 8 = ( 10 101 111.101 010 111 ) 2 quadquad(257.527)_8=(10 101 111.101 010 111)_2 (257.527)8=(10 101 111.101 010 111)2
quad 二进制数 ( 10 101 111.101 010 111 ) 2 (10 101 111.101 010 111)_2 (10 101 111.101 010 111)2 转换为十六进制
( 10 101 111.101 010 111 ) 2 = ( 1010 1111.1010 1011 1000 ) 2 = ( A F . A B 8 ) 16 quadquad(10 101 111.101 010 111)_2=(1010 1111.1010 1011 1000)_2=(AF.AB8)_{16} (10 101 111.101 010 111)2=(1010 1111.1010 1011 1000)2=(AF.AB8)16
- 十进制(Decimal)
⇒
pmb{Rightarrow}
⇒⇒⇒ 二进制(Binary)
quad
quad 以小数点为界,整数部分除以 2,然后取每次得到的商和余数,用商继续和 2 相除,直到商小于 2。然后把第一次得到的余数作为二进制的个位,第二次得到的余数作为二进制的十位,依次类推,最后一次得到的小于 2 的商作为二进制的最高位,这样由商 + 余数组成的数字就是转换后二进制的值(整数部分用除 2 取余法);小数部分则先乘 2,然后获得运算结果的整数部分,将结果中的小数部分再次乘 2,直到小数部分为零。然后把第一次得到的整数部分作为二进制小数的最高位,后续的整数部分依次作为低位,这样由各整数部分组成的数字就是转化后二进制小数的值(小数部分用乘 2 取整法)。
quad
quad 注:需要说明的是,有些十进制小数无法准确的用二进制进行表达,所以转换时符合一定的精度即可,这也是为什么计算机的浮点数运算不准确的原因。
quad
例: 将十进制数 ( 93.3125 ) 10 (93.3125)_{10} (93.3125)10 转换成二进制数。
93.3125 quad93.3125 93.3125 整数部分:
qquad 93/2 = 46 ... 1
qquad 46/2 = 23 ... 0
qquad 23/2 = 11 ... 1
qquad 11/2 = 5 ... 1
qquad 5/2 = 2 ... 1
qquad 2/2 = 1 ... 0
93.3125 quad93.3125 93.3125 小数部分:
qquad 0.3125 x 2 = 0.625 ... 0
qquad 0.625 x 2 = 1.25 ... 1
qquad 0.25 x 2 = 0.5 ... 0
qquad 0.5x2 = 1.0 ... 1
quad 因此, ( 93.3125 ) 10 = ( 1011101.0101 ) 2 (93.3125)_{10}=(1011101.0101)_2 (93.3125)10=(1011101.0101)2 - 十进制(Decimal)
⇒
pmb{Rightarrow}
⇒⇒⇒ 八进制(Octal)
quad
quad 以小数点为界,整数部分除以 8,然后取每次得到的商和余数,用商继续和 8 相除,直到商小于 8。然后把第一次得到的余数作为八进制的个位,第二次得到的余数作为八进制的十位,依次类推,最后一次得到的小于 8 的商作为八进制的最高位,这样由商 + 余数组成的数字就是转换后八进制的值(整数部分用除 8 取余法);小数部分则先乘 8,然后获得运算结果的整数部分,将结果中的小数部分再次乘 8,直到小数部分为零。然后把第一次得到的整数部分作为八进制小数的最高位,后续的整数部分依次作为低位,这样由各整数部分组成的数字就是转化后八进制小数的值(小数部分用乘 8 取整法)。
quad
例: 将十进制数 ( 93.3125 ) 10 (93.3125)_{10} (93.3125)10 转换成八进制数。
93.3125 quad93.3125 93.3125 整数部分:
qquad 93/8 = 11 ... 5
qquad 11/8 = 1 ... 3
93.3125 quad93.3125 93.3125 小数部分:
qquad 0.3125 x 8 = 2.5 ... 2
qquad 0.5 x 8 = 4.0 ... 4
quad 因此, ( 93.3125 ) 10 = ( 135.24 ) 8 (93.3125)_{10}=(135.24)_8 (93.3125)10=(135.24)8 - 十进制(Decimal)
⇒
pmb{Rightarrow}
⇒⇒⇒ 十六进制(Hex)
quad
quad 以小数点为界,整数部分除以 16,然后取每次得到的商和余数,用商继续和 16 相除,直到商小于 16。然后把第一次得到的余数作为十六进制的个位,第二次得到的余数作为十六进制的十位,依次类推,最后一次得到的小于 16 的商作为十六进制的最高位,这样由商 + 余数组成的数字就是转换后十六进制的值(整数部分用除 16 取余法);小数部分则先乘 16,然后获得运算结果的整数部分,将结果中的小数部分再次乘 16,直到小数部分为零。然后把第一次得到的整数部分作为十六进制小数的最高位,后续的整数部分依次作为低位,这样由各整数部分组成的数字就是转化后十六进制小数的值(小数部分用乘 16 取整法)。
quad
例: 将十进制数 ( 93.3125 ) 10 (93.3125)_{10} (93.3125)10 转换成十六进制数。
93.3125 quad93.3125 93.3125 整数部分:
qquad 93/16 = 5 ... 13(D)
93.3125 quad93.3125 93.3125 小数部分:
qquad 0.3125 x 16 = 5.0 ... 5
quad 因此, ( 93.3125 ) 10 = ( 5 D . 5 ) 16 (93.3125)_{10}=(5D.5)_{16} (93.3125)10=(5D.5)16
- 十六进制(Hex)
⇒
pmb{Rightarrow}
⇒⇒⇒ 二进制(Binary)
quad
quad 十六进制转换成二进制与二进制转换成十六进制相反,将一位十六进制数分解成四位二进制数,小数点位置不变。
quad
例: 将十六进制数 ( D 7. A 8 ) 16 (D7.A8)_{16} (D7.A8)16 转换成二进制数
( D 7. A 8 ) 16 = ( 1101 0111.1010 1 ) 2 quad(D7.A8)_{16}=(1101 0111.1010 1)_2 (D7.A8)16=(1101 0111.1010 1)2 - 十六进制(Hex)
⇒
pmb{Rightarrow}
⇒⇒⇒ 八进制(Octal)
quad
quad 将十六进制转换为二进制,然后再将二进制转换为八进制,小数点位置不变。
quad
例: 将十六进制数 ( D 7. A 8 ) 16 (D7.A8)_{16} (D7.A8)16 转换成八进制数
quad 将十六进制数 ( D 7. A 8 ) 16 (D7.A8)_{16} (D7.A8)16 转换成二进制数: ( D 7. A 8 ) 16 = ( 1101 0111.1010 1 ) 2 (D7.A8)_{16}=(1101 0111.1010 1)_2 (D7.A8)16=(1101 0111.1010 1)2
quad 将二进制数 ( 1101 0111.1010 1 ) 2 (1101 0111.1010 1)_2 (1101 0111.1010 1)2 转换成八进制数:
( 1101 0111.1010 1 ) 2 = ( 011 010 111.101 010 ) 2 = ( 327.52 ) 8 qquad(1101 0111.1010 1)_2=(011 010 111.101 010)_2=(327.52)_8 (1101 0111.1010 1)2=(011 010 111.101 010)2=(327.52)8 - 十六进制(Hex)
⇒
pmb{Rightarrow}
⇒⇒⇒ 十进制(Decimal)
quad
quad 将十六进制每位上的数乘以十六进制位权,然后将得出来的数再加在一起。
quad
例: 将十六进制数 ( D 7. A 8 ) 16 (D7.A8)_{16} (D7.A8)16 转换成二进制数
( D 7. A 8 ) 16 = 7 × 1 6 0 + D ( 13 ) × 1 6 1 + A ( 10 ) × 1 6 − 1 + 8 × 1 6 − 2 = 215.65625 quad(D7.A8)_{16}=7times16^0+D(13)times16^1+A(10)times16^{-1}+8times16^{-2}=215.65625 (D7.A8)16=7×160+D(13)×161+A(10)×16−1+8×16−2=215.65625
quad 在介绍 Java 数据类型之前,让我们先了解一下计算机是如何对数值进行存储的。数值在计算机中的表示形式统称为机器数。计算机中处理数据及运算都是采用二进制,通常规定机器数用八位二进制表示。实用的数据有正数和负数,因为计算机只能表示 0、1 两种状态,数据的正号“+”或负号“-”,在计算机里就用一位二进制的 0 或 1 来区别,通常放在最高位,称为符号位。 符号位数值化之后,为能方便的对机器数进行算术运算、提高运算速度,计算机设计了多种符号位与数值一起编码的方法,最常用的机器数表示方法有:原码、反码和补码,下面就分别介绍一下它们的表示方法。
1. 用法- 原码:原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数为 0,负数为 1(0 有两种表示:+0 和 -0),其余位表示数值的大小。
- 反码:对于单个数值(二进制的 0 和 1)而言,对其进行取反操作就是将 0 变为 1,1 变为 0。正数的反码和原码一样,负数的反码就是在原码的基础上符号位保持不变,其他位取反。
- 负数反码转原码(符号位不变,数值位取反)
- 补码:正数的补码和原码,反码相同;负数的补码则是在原码的基础上符号位保持不变,其他位取反,然后在末尾加 1。在计算机系统中,数值一律用补码来表示和存储。
- 负数补码转原码(补码的补码即是原码)
quad 现在我们知道了计算机可以有三种编码方式表示一个数。对于正数因为三种编码方式的结果都相同:[+1] =[0000 0001] 原 _原 原=[0000 0001] 反 _反 反=[0000 0001] 补 _补 补,所以不需要过多解释。
quad 但是对于负数:[-1] =[1000 0001] 原 _原 原=[1111 1110] 反 _反 反=[1111 1111] 补 _补 补,可见原码、反码和补码是完全不同的。
quad 对于计算机来说,加减乘除已经是最基础的运算,要设计的尽量简单。计算机辨别“符号位”会让计算机的基础电路设计变得十分复杂,于是人们想出了将符号位也参与运算的方法。同时,根据运算法则减去一个正数等于加上一个负数,即:1-1=1+(-1)=0,所以机器可以只有加法而没有减法,这样计算机运算的设计就更简单了。于是,人们开始探索将符号位参与运算,并且只保留加法的方法.。
- 首先来看原码计算:
- 计算十进制的表达式:1-1 = 0
- 二进制的表达式:1-1 = 1+(-1) = [0000 0001] 原 _原 原 + [1000 0001] 原 _原 原= [1000 0010] 原 _原 原
- [1000 0010] 原 _原 原 转换成十进制即为 -2,由此可见如果使用原码表示,让符号位也参与计算,显然对于减法来说,结果是不正确的,这也就是为何计算机内部不使用原码表示一个数。为了解决原码做减法的问题,出现了反码。
- 反码操作:
- 计算十进制的表达式:1-1 = 0
- 二进制的表达式:1-1 = 1+(-1) = [0000 0001] 原 _原 原+ [1000 0001] 原 _原 原= [0000 0001] 反 _反 反+ [1111 1110] 反 _反 反= [1111 1111] 反 _反 反= [1000 0000] 原 _原 原
- [1000 0000] 原 _原 原 转换成十进制即为 -0,由此发现使用反码计算减法,结果的真值部分是正确的。而唯一的问题其实就出现在“0”这个特殊的数值上。虽然人们理解上 +0和 -0 是一样的, 但是 0 带符号是没有任何意义的,而且会有 [0000 0000] 原 _原 原 和 [1000 0000] 原 _原 原 两个编码表示 0。于是补码的出现,解决了 0 的符号以及两个编码的问题。
- 补码运算:
- 计算十进制的表达式:1-1 = 0
- 二进制的表达式:1-1 = 1+(-1) = [0000 0001] 原 _原 原+ [1000 0001] 原 _原 原= [0000 0001] 补 _补 补+ [1111 1111] 补 _补 补= [0000 0000] 补 _补 补=[0000 0000] 原 _原 原
- [0000 0000] 原 _原 原 转换成十进制即为 0,这样 0 用 [0000 0000] 表示,而以前出现问题的 -0 则不存在了。
- 可以用 [1000 0000] 表示 -128:-1-127 = (-1)+(-127) = [1000 0001] 原 _原 原+ [1111 1111] 原 _原 原= [1111 1111] 补 _补 补+ [1000 0001] 补 _补 补= [1000 0000] 补 _补 补
- 在使用补码运算的结果中,[1000 0000] 补 _补 补 就是 -128,但是注意因为实际上是使用以前的 -0 的补码来表示 -128,所以 -128 并没有原码和反码表示。(对 -128 的补码表示 [1000 0000] 补 _补 补 算出来的原码是 [0000 0000] 原 _原 原,这是不正确的)
quad 使用补码,不仅仅修复了 0 的符号以及存在两个编码的问题,而且还能够多表示一个最低数。这就是为什么 8 位二进制,使用原码或反码表示的范围为 -127 ~ 127,而使用补码表示的范围为 -128 ~ 127。
quad 也正因为机器使用补码来表示和存储,所以对于编程中常用到的 32 位 int 类型,可以表示范围是: [ − 2 31 , 2 31 − 1 -2^{31}, 2^{31}-1 −231,231−1],因为第一位表示的是符号位,而使用补码表示时又可以多保存一个最小值。
2.3.3 基本数据类型 1. 数值类型(有符号数值需要保留一个二进制位存储符号)quad 整数在计算机中一般使用整型处理,其在内存中的存储形式为二进制补码。
(1)整数类型(1 个字节(byte)为 8 个二进制位(bit))- byte:占用 1 个字节,范围 [ − 2 7 , 2 7 − 1 -2^7, 2^7-1 −27,27−1],即 -128 ~ 127。
- short:占用 2 个字节,范围 [ − 2 15 , 2 15 − 1 -2^{15}, 2^{15}-1 −215,215−1],即 -32768 ~ 32767。
- int:占用 4 个字节,范围 [ − 2 31 , 2 31 − 1 -2^{31}, 2^{31}-1 −231,231−1],即 -2147483648 ~ 2147483647。
- long:占用 8 个字节,范围 [ − 2 63 , 2 63 − 1 -2^{63}, 2^{63}-1 −263,263−1],即 -9223372036854774808 ~ 9223372036854774807。常在数值后加 “L”,“L” 理论上不区分大小写,但是若写成 “l” 容易与数字 “1” 混淆,不容易分辩。所以最好大写。
quad 计算机对于浮点类型的数据采用单精度类型(float)和双精度类型(double)来存储,分为符号位(0正,1负)、指数位、尾数三部分(注:符号位表示的是尾数的符号而不是指数部分的符号),其中指数位存储科学计数法中的指数数据,并且采用移位存储(127+指数)的方式,这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差。java 的 float 只能用来进行科学计算或工程计算,在大多数的商业计算中,一般采用 java.math.BigDecimal 类来进行精确计算。其实不论是 float 还是 double 在存储方式上都是遵从 IEEE 的规范的,float 遵从的是 IEEE R32.24,而 double 遵从的是 IEEE R64.53。
quad IEEE R32.24和 IEEE R64.53 的存储方式都是用科学计数法来存储数据的,比如 8250 用十进制的科学计数法表示就为: 8.25 × 1 0 3 8.25times10^3 8.25×103。而计算机根本不认识十进制的数据,他只认识 0、1,所以在计算机存储中,首先要将上面的数更改为二进制的科学计数法表示,8250 用二进制表示可表示为10000000111010,用二进制的科学计数法表示 10000000111010 可以表示为 1.0000000111010 × 2 13 1.0000000111010times2^{13} 1.0000000111010×213。对于任意数值表示成二进制科学计数法以后,一定是 1 点几(尾数)乘以 2 的多少次方(指数)。对于小于零的负数来说,就是负 1 点几(尾数)乘以 2 的多少次方(指数)。因为任意数值表示成二进制科学计数法这种形式时最高位都是 1,所以在存储时实际上并不保存这一位,这使得 float 的 23bit 的尾数实际可以表示 24bit 的精度,double 中 52bit 的尾数可以表达 53bit 的精度。
- float:占用 4 个字节,即 32 个二进制位。float 的取值范围为
−
2
128
-2^{128}
−2128 ~
2
128
2^{128}
2128,也即
−
3.4028237
e
+
38
-3.4028237e+38
−3.4028237e+38 ~
3.4028237
e
+
38
3.4028237e+38
3.4028237e+38。常在数值后加 “f”,“f” 不区分大小写。
- 1 b i t 1bit 1bit(符号位,占据最高位(第 31 位),用于表示浮点数是正数还是负数,为 0 表示正数,为 1 表示负数)
-
8
b
i
t
s
8bits
8bits(指数位,占据第 30 位到第 23 位这 8 位),float 的指数范围为 -127 ~ 128。
- 浮点型的指数位都有一个固定的偏移量(bias),用于使指数+这个偏移量=一个非负整数,这样指数位部分就不用为如何表示负数而担心了。
- 规定:在 32 位单精度类型中, 这个偏移量是 127;在 64 位双精度类型中,偏移量是 1023。
- 指数位决定了大小范围。其中负指数决定了浮点数所能表达的绝对值最小的非零数;而正指数决定了浮点数所能表达的绝对值最大的数,也即决定了浮点数的取值范围。
-
23
b
i
t
s
23bits
23bits(尾数位,占据剩余的 22 位到 0 位这 23 位,尾数位用的是原码)
- 尾数位决定了计算精度。 f l o a t : 2 23 = 8388608 float:2^{23}=8388608 float:223=8388608,一共 7 位,这意味着最多能有 7 位有效数字,但绝对能保证的为 6 位,也即 float 的精度为 6 ~ 7 位有效数字.
- 示例:float 存储 8250(10000000111010)
- double:占用 8 个字节,即 64 个二进制位。double 的取值范围为
−
2
1024
-2^{1024}
−21024 ~
2
1024
2^{1024}
21024,也即
−
1.79
e
+
308
-1.79e+308
−1.79e+308 ~
1.79
e
+
308
1.79e+308
1.79e+308。
- 1 b i t 1bit 1bit(符号位,占据最高位(第 63 位),用于表示浮点数是正数还是负数,为 0 表示正数,为 1 表示负数)
- 11 b i t s 11bits 11bits(指数位,占据第 62 位到第 52 位这 11 位),double 的指数范围为 -1023 ~ 1024。
-
52
b
i
t
s
52bits
52bits(尾数位,占据剩余的 51 位到 0 位这 52 位,尾数位用的是原码)
- 尾数位决定了计算精度。 d o u b l e : 2 52 = 4503599627370496 double:2^{52}=4503599627370496 double:252=4503599627370496,一共 16 位,同理,double 的精度为 15 ~ 16 位。
- 示例:double 存储 8250(10000000111010)
quad 以 32 位单精度 float 内存模型为例
quad 如图所示,通常情况下 8 位存储空间可以存储的数值范围为00000000 ~ 11111111,也就是从 0 开始到 255 结束,一共 256 个数。但是浮点数的幂指数(阶码:在机器中表示一个浮点数时需要给出指数,这个指数用整数形式表示,这个整数叫做阶码)是有必要使用负数的。
quad 既要表示正数,又要表示负数,我们就需要拿出一位来表示正负号,使用传统的方式,即一个字节的最高位(最左边那位)为 1 时表示负数,为 0 时表示正数,那么我们可以得到两个区间:0 0000000~ 0 1111111,即 +0 到 127;1 0000000~ 1 1111111,即 -0 到 -127。这样就会出现 2 个 0,一个 +0,一个 -0。
quad 使用移位存储方式会有什么效果呢? 这里我们使用单精度类型(float)举例,float移位存储要在原指数基础上加偏移量127(0111 1111) 。
如果我们要表示 0,则有 0 + 127 = 127,即 00000000 + 01111111 = 01111111 如果我们要表示 1,则有 1 + 127 = 128,即 00000001 + 01111111 = 10000000 如果我们要表示 2,则有 2 + 127 = 129,即 00000010 + 01111111 = 10000001 ...... 如果我们要表示 128,则有 128 + 127 = 255 即 10000000 + 01111111 = 11111111 这个 128 是我们能够使用 8 位二进制移位存储算法表示的最大正数,再大就会溢出。 同样,我们来看看负数: ...... 如果我们要表示 -1 时,则有 (-1) + 127 = 126 即 01111111 - 00000001 = 01111110 如果我们要表示 -2 时,则有 (-2) + 127 = 125 即 01111111 - 00000010 = 01111101 ...... 如果我们要表示 -127 时,则有 (-127) + 127 = 0 即 01111111 - 01111111 = 00000000 这个 -127 是我们能够使用 8 位二进制移位存储算法表示的最小负数,再小就会溢出。
quad 由上面的例子,我们可以得出规律,采用移位存储技术,我们可以使用 8 位二进制来表示从 -127~128,共计:127 个负数 + 零(0) + 128 个正数 = 256 个数。
quad 为什么要用移码表示阶码,而不用补码表示阶码? 采用这种方式表示的目的是为了简化比较。因为指数必须是有符号数才能表达很大或很小的数值,如果采用补码表示的话,首先,尾数是有符号的,如果指数也是有符号的,那么就不能简单的对浮点数进行大小比较,因为根据补码比较大小的话,要先将补码转换成原码再进行比较。正因为如此,将指数的值调整到一个正值的范围内以便进行比较。所以移码不存在符号位,我们直接可以由移码的表示形式看出对应数值的大小。
(3)字符类型quad Java 中的 char 类型占用 2 个字节(16bits),可以存放单个汉字、单个字母、单个数字和其他 Unicode 字符等(例:a=97、a='u0061'、A=65、A=‘u0041’)。所有字符的本质还是数字,最小值是 u0000(十进制等效值为 0);最大值是 uffff(十进制等效值为 65535)。另外,字母前面加上斜线""来表示常见的那些不能显示的ASCII字符,称为转义字符。如: (空字符(NULL))、t、n等,就称为转义字符,因为后面的字符,都不是它本来的ASCII字符意思了。
2. boolean 类型- Java 将 boolean 视为完全独立的数据类型,该数据类型具有 2 个不同的值:true 和 false。
- 值 1 和 0 为 int 类型,不能隐式转换为 boolean,所以不可以直接赋给 boolean 数据类型。
- boolean 类型的变量在底层实际会调用 int,那么既然 int 占用 4 个字节,boolean 也自然占用 4 个字节。
- boolean 类型的数组在底层实际会调用 byte,那么既然 byte 占用 1 个字节,boolean 数组中的 boolean 也就占用 1 个字节。
- 类
- 接口
- 数组



