一、java中八大基本数据类型所占内存大小

从小到大的排序分别是:(记住是11224488就容易记忆了)

boolean:理论上只需要一个字符(1/8个字节),但实际按照一个字节处理。

byte:1个字节(-128~127)

char:2个字节

short: 2个字节

float:4个字节

int:4个字节

double:8个字节

long:8个字节

二、java的数据在内存中的存储形式

1、数据的二进制表示有三种:原码、反码、补码。Java中用补码形式表示数据。

2、什么是原码:

第一位正负位,1表示负,0表示正。

其余各位是二进制数表示,例如3和-3的原码如下:

      3的原码00000011   -3的原码 10000011

3、什么是反码:正数是原码本身。负数原码按位取反(符号位不变)。例如3和-3的反码如下:

      3的反码00000011   -3的反码11111100

4、什么是补码:正数是原码本身。负数反码加1。

      3的补码是00000011  -3的补码是11111101

举一个简单的例子:

int a=-3;

byte b=-3;

内存中a b的存储是这样的:(int占4个字节,32位。byte占1个字节,8位)

a=-3没什么好说的,按照补码存储(就是反码+1):

int a = -3       11111111 11111111   11111111   11111101

b=-3,分为两步,第一步求出int -3的32位补码,然后截取后面的8位,舍弃前面的24位。因此:

byte b = -3     11111101

三、java中数据的强制转换问题

java中数据类型转换分为两种:自动类型转换和强制类型转换

1、自动类型转换:编译器会自动完成类型转换,不需要在程序中编写代码

转换规则:从存储范围小的类型到存储范围大的类型。

具体规则:byte→short(char)→int→long→float→double.

这里可能有人有疑问:前面不是说了long在内存中占8个字节(64位),float只占4个字节(32位),为什么long转换为float是从小范围转换到大范围呢?这是因为float浮点类型的数据在内存中的存储式中这样的:V=(-1)^s * M * 2^E。对于一个32位的float的数据,第1位表示符号位,即S。接下来的8位表示指数域,即E。剩下的23位,小数域,即M,M的取值范围为[1,2)或[0,1)。也就是说,浮点数在内存中的二进制值不是直接转换为十进制数值的,而是按照上述公式计算而来,通过这个公式,虽然只用到了4个字节,但是浮点数却比长整型的最大值要大。这也就是为什么在数据转换的时候,long类型转换为float类型的是从小到大范围转换的根本原因所在!

2、强制类型转换:必须在程序中编写代码。该类型转换很可能存在精度的损失。

转换规则:从存储范围大的类型到存储范围小的类型。

具体规则:double→float→long→int→short(char)→byte.

本人一般这样理解记忆,自动类型转换是很自然的类型转换,就好像人的成长过程,从小到大,自然完成,不需要任何附加手段。而强制类型转换,就好像要人返老还童,从大到小,违背自然规律,所以必须加一些强制手段,但是就算返老还童成功,也会有一定的后遗症,也就是精度损失。

这里举个简单的强制类型转换的例子:

short a = 128;

byte b = (byte) a;

short a=128为正数,在内存中以补码存储为:00000000 10000000

强制转换成byte,截取后8位,舍弃前八位,则b在内存中存储为:10000000。因为开头是1,所以为负数。即1个负数的补码是10000000。反码就是01111111(补码-1),原码是1000000(反码取反)。是128. 因为是负数,所以是-128。也就是最终结果是b=-128。

总结:弄清楚java所有类型转换的核心点就是分清楚是从小到大还是从大到小(是自然长大还是返老还童),自然长大就是符合规律,不需要外加手段就能转换,返老还童就是违背规律,需要加强制转换手段。当然这是建立在熟记每种数据类型的内存大小的基础上的。记住“11224488”口诀,并把float和double单独拎出来理解记忆就好了。