java基础类型
bit 普及
是二进制数的一位包含的信息或2个选项中特别指定1个的需要信息量称为一比特,是表示信息的最小单位,只有两种状态:0和1。这两个值也可以被解释为逻辑值(真/假、yes/no)、代数符号(+/-)、激活状态(on/off)或任何其他两值属性。
1byte = 8bit
byte(1byte)
- byte 数据类型是8位、有符号的,以二进制补码表示的整数;
- 最小值是 -128(-2^7);
- 最大值是 127(2^7-1);
- 默认值是 0;
- byte 类型用在大型数组中节约空间,主要代替整数,因为 byte 变量占用的空间只有 int 类型的四分之一;
- 封装类型Byte
- 例子:byte a = 100,byte b = -50。
short(2byte)
- short 数据类型是 16 位、有符号的以二进制补码表示的整数
- 最小值是 -32768(-2^15);
- 最大值是 32767(2^15 - 1);
- Short 数据类型也可以像 byte 那样节省空间。一个short变量是int型变量所占空间的二分之一;
- 默认值是 0;
- 封装类型Short
- 缓存对象ShortCache,范围-128到127
- 例子:short s = 1000,short r = -20000。
char(2byte)
- char类型是一个单一的 16 位 Unicode 字符;
- 最小值是 \u0000(即为0);
- 最大值是 \uffff(即为65,535);
- char 数据类型可以储存任何字符;
- 封装对象Character
- 缓存对象ByteCache,范围0到127
- 例子:char letter = ‘A’。
int(4byte)
- int 数据类型是32位、有符号的以二进制补码表示的整数;
- 最小值是 -2,147,483,648(-2^31);
- 最大值是 2,147,483,647(2^31 - 1);
- 一般地整型变量默认为 int 类型;
- 默认值是 0 ;
- 封装类型Integer
- 缓存对象IntegerCache,范围-128到127,可通过参数改变范围
- 例子:int a = 100000, int b = -200000。
long(8byte)
- long 数据类型是 64 位、有符号的以二进制补码表示的整数;
- 最小值是 -9,223,372,036,854,775,808(-2^63);
- 最大值是 9,223,372,036,854,775,807(2^63 -1);
- 这种类型主要使用在需要比较大整数的系统上;
- 默认值是 0L;
- 封装类型Long
- 缓存对象LongCache,范围-128到127
- 例子: long a = 100000L,Long b = -200000L。
- “L”理论上不分大小写,但是若写成”l”容易与数字”1”混淆,不容易分辩。所以最好大写。
float(4byte)
- float 数据类型是单精度、32位、符合IEEE 754标准的浮点数;
- float 在储存大型浮点数组的时候可节省内存空间;
- 默认值是 0.0f;
- 浮点数不能用来表示精确的值,如货币;
- 封装类型Float
- 例子:float f1 = 234.5f。
double(8byte)
- double 数据类型是双精度、64 位、符合IEEE 754标准的浮点数;
- 浮点数的默认类型为double类型;
- double类型同样不能表示精确的值,如货币;
- 默认值是 0.0d;
- 封装类型Double
- 例子:double d1 = 123.4。
boolean(1byte)
- boolean数据类型表示一位的信息;
- 只有两个取值:true 和 false;
- 这种类型只作为一种标志来记录 true/false 情况;
- 默认值是 false;
- 封装类型Boolean
- 例子:boolean one = true。
具有缓存机制的类
Byte、Short、Integer、Long、Character都具有缓存机制。缓存工作都是在静态块中完成,在类生命周期(loading verify prepare resolving initial using unload)的初始化阶段执行。
缓存范围
Byte,Short,Integer,Long为 -128 到 127,Character范围为 0 到 127
是否可以改变缓存范围
除了Integer可以指定缓存范围,其它类都不行。
Integer的缓存上界high可以通过jvm参数-XX:AutoBoxCacheMax=size指定,取指定值与127的最大值并且不超过Integer表示范围,而下界low不能指定,只能为-128
类型转换
同种类型转换
基本类型和封装类型之间存在自动拆箱/自动封箱的操作。
隐式类型转换
从左向右自动转换:byte->short(char)->int->long->float->double。
显式类型转换(强制转换)
从右向左强制转换会精度损失,截止截取位数,从左至右,手动加0.5,进行四舍五入。double->float->long->int->short(char)->byte。
整数负数表示
计算机中的有符号数有三种表示方法,即原码、反码和补码。
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理;同时,加法和减法也可以统一处理。
原码
原码(true form)是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位):正数该位为0,负数该位为1(0有两种表示:+0和-0),其余位表示数值的大小。
反码
反码通常是用来由原码求补码或者由补码求原码的过渡码。
符号位不变,其余各位取反。
补码
首先,正数的原码,反码,补码都是相同的。
负数,是原码,符号位不变,取反再+1;
浮点类型二进制解释
32位单精度二进制 = [1个符号位] [8个阶码位] [23个尾数位]
64位单精度二进制 = [1个符号位] [11个阶码位] [52个尾数位]
小数 = [正负符号位] [整数部分] . [小数部分]
8位阶码位移码偏移量127,11位阶码位移码偏移量1023
小数转二进制
例如:-3.14
第一步:符号位
负用1表示,正的用0,所以[1个符号位] 是1
第二步:整数直接转换成二进制
模2取余法。即递归除以2,直到商为0,余数反转。
或者按二进制每位转为10位数,累加
十进制3=二进制0000 0011
第三步:将小数转换成二进制
十进制0.14=二进制0010 0011 1101 0111 0000 1010 0011 1101 0111 0000 其中010 0011 1101 0111 0000 1是循环的
计算过程:
0.14 x 2 = 0.28 取整得0 取上次结果的小数部分乘以2
0.28 x 2 = 0.56 取整得0 取小数部分为0.56
0.56 x 2 = 1.12 取整得1 取小数部分为0.12
0.12 x 2 = 0.24 取整得0 取小数部分为0.24
0.24 x 2 = 0.48 取整得0 取小数部分为0.48
0.48 x 2 = 0.96 取整得0 取小数部分为0.96
0.96 x 2 = 1.92 取整得1 取小数部分为0.92
0.92 x 2 = 1.84 取整得1 取小数部分为0.84
0.84 x 2 = 1.68 取整得1 取小数部分为0.68
0.68 x 2 = 1.36 取整得1 取小数部分为0.36
0.36 x 2 = 0.72 取整得0 取小数部分为0.72
0.72 x 2 = 1.44 取整得1 取小数部分为0.44
0.44 x 2 = 0.88 取整得0 取小数部分为0.88
0.88 x 2 = 1.76 取整得1 取小数部分为0.76
0.76 x 2 = 1.52 取整得1 取小数部分为0.52
0.52 x 2 = 1.04 取整得1 取小数部分为0.04
0.04 x 2 = 0.08 取整得0 取小数部分为0.08
0.08 x 2 = 0.16 取整得0 取小数部分为0.16
0.16 x 2 = 0.32 取整得0 取小数部分为0.32
0.32 x 2 = 0.64 取整得0 取小数部分为0.64
0.64 x 2 = 1.28 取整得1 取小数部分为0.28
0.28 x 2 = 0.56 取整得0 取小数部分为0.56
回到了开始,进行循环
第四步:移动小数点计算阶码
整数二进制.小数二进制
=0000 0011.0010 0011 1101 0111 0000 1010 0011 1101 0111 0000
移动小数点,使二进制变成1.xxx*2^n形式(规格化)
=0000 001.10010 0011 1101 0111 0000 1010 0011 1101 0111 0000*2^1
指数的值是1加上(8位阶码位移码偏移量127)=128
1+127=128
128的二进制是1000 0000 所以[8个阶码位]是1000 0000
第五步:截取位数
取1.xxx形式小数点后23位得到[23个尾数位]=1 0010 0011 1101 0111 0000 1010 0011 110 (取23位)
即1 0010 0011 1101 0111 0000 10
第六步:组合二进制
32位单精度二进制 = [1个符号位] [8个阶码位] [23个尾数位]
= [1] [1000 0000] [1 0010 0011 1101 0111 0000 10]
= 1100 0000 0100 1000 1111 0101 1100 0010
双精度同理
二进制转小数
例如:(单精度)1100 0000 0100 1000 1111 0101 1100 0010
第一步:按位分段
1100 0000 0100 1000 1111 0101 1100 0010
1 1000 0000 1001 0001 1110 1011 1000 010
[1] [1000 0000] [1001 0001 1110 1011 1000 010]
1代表负数
第二步:计算指数
1000 0000阶码=十进制128,减去8位阶码位移码偏移量127
128 - 127 = 1
在23位尾数前加1.变成 1.[23个尾数],然后向右移动1位(负数向左,正数向右)– 和坐标轴方法一样
1.1001 0001 1110 1011 1000 010右移1位变为:11.001 0001 1110 1011 1000 010
第三步:计算小数
转换成小数=2^1 + 2^0 + 2^-3 + 2^-7 + 2^-8 + 2^-9 + 2^-10 + 2^-12 + 2^-14 + 2^-15 + 2^-16 + 2^-21
= 2 + 1 + 0.125 + 0.0078125 + 0.00390625 + 0.001953125 + 0.0009765625 + 0.000244140625 + 0.00006103515625 + 0.000030517578125 + 0.0000152587890625 + 0.000000476837158203125 = 3.139999866485595703125
因为是负数,所以最终十进制数为=-3.139999866485595703125 ≈ -3.14
所以说,小数部分是无法准确表示的,这也就是float和double无法用于计算金融或货币的原因。计算的话要用BigDecimal。详解请看java基础 BigDecimal