Java中的数值位数
Primitive Data Types原生数据类型(共8种)
类型 | 位数 | 最小值 | 最大值 |
---|---|---|---|
byte | 8-bit | -128=-27 | 127=27-1 |
short | 16-bit | -32768 | 32767 |
int | 32-bit | -231 | 231-1 |
long | 64-bit | -263 | 263-1 |
float | 32-bit | ||
double | 64-bit | ||
boolean | 1-bit | true和false | |
char | 16-bit | \u0000(or 0) | \uffff (or 65,535 inclusive) |
原生类型的默认值Default Values
Data Type | Default Value (for fields) |
---|---|
byte | 0 |
short | 0 |
int | 0 |
long | 0L |
float | 0.0f |
double | 0.0d |
char | ‘\u0000’ |
String (or any object) | null |
boolean | false |
以Integer为例解释Integer的二进制表示法
最小值为0x80000000
,最大值为0x7fffffff
,因为最高位是符号位。
int型为4字节。在计算机内部数值的二进制表示,有正码、反码和补码。一般采用二进制补码进行表示和运算,MIN_VALUE = 0x80000000
和 MAX_VALUE = 0x7fffffff
就是补码表示的Integer的最小值(-2^31)和最大值(2^31-1)。
一个 Integer 类型占 4 字节,一个字节占 8 位二进制码,因此一个 Integer 总共占 32 位二进制码。去除第一位的符号位,剩下 31 位来表示数值。
- 当原码为正数的时候,正数的原码、反码、补码都相同。
- 当原码为负数的时候,反码为去除符号位按位取反,补码为去除符号位按位取反再加1。
原码:1000 0000 0000 0000 0000 0000 0000 0001 -1
反码:1111 1111 1111 1111 1111 1111 1111 1110
补码:1111 1111 1111 1111 1111 1111 1111 1111
原码:1000 0000 0000 0000 0000 0000 0000 0010 -2
反码:1111 1111 1111 1111 1111 1111 1111 1101
补码:1111 1111 1111 1111 1111 1111 1111 1110
原码:1111 1111 1111 1111 1111 1111 1111 1111 -(2^31 - 1)= -2^31 + 1
反码:1000 0000 0000 0000 0000 0000 0000 0000
补码:1000 0000 0000 0000 0000 0000 0000 0001
原码:1000 0000 0000 0000 0000 0000 0000 0000 -0 约定为 -2^31
反码:1111 1111 1111 1111 1111 1111 1111 1111
补码:1000 0000 0000 0000 0000 0000 0000 0000
如何证明最高位为符号位
for (int i = Integer.MIN_VALUE; i < 0; i++) {
assertEquals(1, i >>> 31);
}
for (int i = 0; i < Integer.MAX_VALUE ; i++) {
assertEquals(0, i >>> 31);
}
// << Signed left shift,
// >> Signed right shift,
// >>> Unsigned right shift, 没有<<<这个符号.
int target = 1;
for (int i = 0; i < 31; i++) {
assertTrue( 1 << target > 0);
}
//0_000000...0000_0
//0_000000...0000_1
//0_000000...0001_0
//0_000000...0010_0
//0_000000...0100_0
//0_000000...1000_0
十六进制表示数值的时候,默认是int。
assertEquals((short) 0x8000, Short.MIN_VALUE);
十六进制数表示数值的时候的特例
assertTrue(-0x8000_0000 < 0);
assertEquals(0x1, 1);
assertEquals(-0x1, -1);
关于数值的溢出问题
最大值加1或者最小值减1后会溢出。两个符号相同的数相加才可能溢出。
为了防止溢出可以使用Math.addExact()
方法。
assertEquals(Integer.MAX_VALUE + 1000, Integer.MIN_VALUE + 999);
assertEquals(Integer.MAX_VALUE + 1, Integer.MIN_VALUE);
assertEquals(Integer.MIN_VALUE + 1, 0x8000_0001);
assertEquals(-1, 0xffff_ffff);
assertEquals(0x0000_0000, 0xffff_ffff + 1);
assertEquals(0x8000_0000 + 0xffff_ffff, 0x7fff_ffff);
int
转short
的时候高位直接被舍弃,没有符号位。- 16进制表示法
0x1234_5678
中间的下划线无意义,便于阅读。官方文档的说明