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