这里介绍一下Java的几个基本类型Short Integer Long Float Double,以及他们的取值范围,内存占用字节数,还有他们在内存中具体是如何存储的。
1.Short 2字节取值范围是-2^15 ~ (2^15-1)
public final class Short extends Number implements Comparable<Short> {
/**
* A constant holding the minimum value a {@code short} can
* have, -2<sup>15</sup>.
*/
public static final short MIN_VALUE = -32768;
/**
* A constant holding the maximum value a {@code short} can
* have, 2<sup>15</sup>-1.
*/
public static final short MAX_VALUE = 32767;
...
}
可以从系统源码中看到MIN_VALUE = -32768 MAX_VALUE = 32767,
符号位(S):1bit | 尾数位(M):15bit |
由于short类型是2字节(16位)表示的,第1位为符号位,后面15位存储数值,所以取值范围是-2^15 ~ (2^15-1)
2.Integer 4字节取值范围 -2^31 ~ (2^31 - 1)
public final class Integer extends Number implements Comparable<Integer> {
/**
* A constant holding the minimum value an {@code int} can
* have, -2<sup>31</sup>.
*/
@Native public static final int MIN_VALUE = 0x80000000;
/**
* A constant holding the maximum value an {@code int} can
* have, 2<sup>31</sup>-1.
*/
@Native public static final int MAX_VALUE = 0x7fffffff;
...
}
可以从源码中看到 MIN_VALUE = 0x80000000 MAX_VALUE = 0x7fffffff 这里需要注意的是前面有@Native注解,所以这里是实际在内存中存储的形式。可以看到最小值0x80000000反而比最大值0x7fffffff大1,这是为什么呢?写成2进制就可以理解
0x80000000 -> 1000 0000 0000 0000 0000 0000 0000 0000
0x7fffffff -> 0111 1111 1111 1111 1111 1111 1111 1111
带符号存储规定第一位表示符号位,0表示正数,1表示负数,所以最大值是0x7fffffff也就是(2^31 - 1)应该没什么问题了。然后负数采用补码的形式来存储,0x80000000第一位是1所以是负数,得到其绝对值就是2^31,所以0x80000000表示的值是-2^31。
Integer类型是由4字节表示的,取值范围就是-2^31 ~ (2^31 - 1)
3.Long 8字节取值范围-2^63 ~ (2^63 - 1)
public final class Long extends Number implements Comparable<Long> {
/**
* A constant holding the minimum value a {@code long} can
* have, -2<sup>63</sup>.
*/
@Native public static final long MIN_VALUE = 0x8000000000000000L;
/**
* A constant holding the maximum value a {@code long} can
* have, 2<sup>63</sup>-1.
*/
@Native public static final long MAX_VALUE = 0x7fffffffffffffffL;
...
}
Long与Short Integer都比较类似,都是用来表示整数的,唯一的区别就是长度不一样,并且它是由8字节表示的,所以直接可以类推出取值范围-2^63 ~ (2^63 - 1)
4.Float 正数取值范围2^-149 ~ (2-2^-23)*2^127
public final class Float extends Number implements Comparable<Float> {
/**
* A constant holding the positive infinity of type
* {@code float}. It is equal to the value returned by
* {@code Float.intBitsToFloat(0x7f800000)}.
*/
public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
/**
* A constant holding the negative infinity of type
* {@code float}. It is equal to the value returned by
* {@code Float.intBitsToFloat(0xff800000)}.
*/
public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
/**
* A constant holding a Not-a-Number (NaN) value of type
* {@code float}. It is equivalent to the value returned by
* {@code Float.intBitsToFloat(0x7fc00000)}.
*/
public static final float NaN = 0.0f / 0.0f;
/**
* A constant holding the largest positive finite value of type
* {@code float}, (2-2<sup>-23</sup>)·2<sup>127</sup>.
* It is equal to the hexadecimal floating-point literal
* {@code 0x1.fffffeP+127f} and also equal to
* {@code Float.intBitsToFloat(0x7f7fffff)}.
*/
public static final float MAX_VALUE = 0x1.fffffeP+127f; // 3.4028235e+38f
/**
* A constant holding the smallest positive normal value of type
* {@code float}, 2<sup>-126</sup>. It is equal to the
* hexadecimal floating-point literal {@code 0x1.0p-126f} and also
* equal to {@code Float.intBitsToFloat(0x00800000)}.
*
* @since 1.6
*/
public static final float MIN_NORMAL = 0x1.0p-126f; // 1.17549435E-38f
/**
* A constant holding the smallest positive nonzero value of type
* {@code float}, 2<sup>-149</sup>. It is equal to the
* hexadecimal floating-point literal {@code 0x0.000002P-126f}
* and also equal to {@code Float.intBitsToFloat(0x1)}.
*/
public static final float MIN_VALUE = 0x0.000002P-126f; // 1.4e-45f
...
}
从上面源码可以看到,Float源码中,定义了很多特殊的值。不光只有最大值和最小值。
先介绍一下Float的存储格式4字节表示,32位
符号位(S):1bit | 指数位(E):8bit | 尾数位(M):23bit |
符号位,0表示正数,1表示负数。
指数位,需要同时表示正指数和负指数,使用EXCESS形式表示。0111 1111表示0 ,1000 0000 表示1, 0111 1110表示-1。但是1111 1111和0000 0000有特殊用途,无法使用,所以指数的取值范围是0000 0001 ~ 1111 1110也就是-126 ~ 127。
尾数位,需要和指数位配合使用,把数值按标准表示,以1.1001 * 2^10(整数部分必须为1)这种形式表示。 比如,1.01就是表示为1.01*2^0,那么指数位(E)=0111 1111 尾数为(M)=0100 00...00(整数部分省略)
完整表示就是 0 01111111 0100 0000 0000 0000 0000 000
0.0011完整表示就是 0 01111100 1000 0000 0000 0000 0000 000
由于这个存储特性,所以就有几个特殊值需要存储:
正无穷大,POSITIVE_INFINITY = 1.0f / 0.0f 0x7f800000 -> 0 11111111 000...0000
负无穷大,NEGATIVE_INFINITY = -1.0f / 0.0f 0xff800000 -> 1 11111111 000...0000
NaN,0.0f / 0.0f 0x7fc00000 -> 0 11111111 100...0000
正最大值,MAX_VALUE = 0x7f7fffff -> 0 11111110 111...1111 (2-2^-23)*2^127
正最小值,MIN_NORMAL = 0x00800000 -> 0 00000001 000...0000 (1.0*2^-23)*2^-126 = 2^-149
5.Double
8字节表示,64位
符号位(S):1bit | 指数位(E):11bit | 尾数位(M):52bit |
Double类型与Float相似,只不过指数位=11和尾数位=52有差别,其他存储没有差异。