整数型数据在java中有三种表示方式,分别是十进制、八进制、十六进制。默认为十进制,以0开始表示八进制,以0x开始表示十六进制。
● 十进制:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17...
● 八进制:0,1,2,3,4,5,6,7,10,11,12,13,14,15,16,17,20,21...
● 十六进制:0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,10,11...
在java语言当中,整数型字面量被当做int类型处理,如果想表示long类型则需要在字面量后面添加L/l,建议大写L,因为小写l和1不好区分。请看以下程序:
public class IntegerTypeTest01 {
public static void main(String[] args) {
//十进制
int a = 10;
System.out.println("a = " + a);
//八进制
int b = 010;
System.out.println("b = " + b);
//十六进制
int c = 0x10;
System.out.println("c = " + c);
}
}
运行结果如下图所示:
图4-5:十、八、十六进制
接下来继续看以下代码:
public class IntegerTypeTest02 {
public static void main(String[] args) {
//声明一个int类型的变量a
//100被默认当做int类型处理
//以下代码不存在类型转换
int a = 100;
//100被默认当做int类型处理,占用4个字节
//b变量是long类型,默认可容纳8个字节
//小容量转换成大容量,叫做自动类型转换
long b = 100;
//b变量long类型,占用8个字节
//c变量int类型,占用4个字节
//大容量不能直接赋值给小容量,编译报错了
//int c = b;
//强制类型转换需要添加强制类型转换符
//强制类型转换时可能引起精度损失,谨慎使用
int c = (int)b;
//a是int类型
//b是long类型
//c是int类型
//多种数据类型混合运算时先转换成容量最大的再做运算
//最终的结果是long类型,大容量无法直接赋值给小容量
//所以编译报错了
//int d = a + b + c;
//解决以上编译错误
int d = (int)(a + b + c);
System.out.println("d = " + d);
//或者
long d2 = a + b + c;
System.out.println("d2 = " + d2);
//100L被当做long类型处理
//x变量是long类型
//不存在类型转换
long x = 100L;
System.out.println("x = " + x);
}
}
运行结果如下图所示:
图4-6:整数型测试
通过以上代码的学习,我们知道小容量转换成大容量叫做自动类型转换,大容量转换成小容量叫做强制类型转换,强制类型转换要想编译通过必须添加强制类型转换符,虽然编译通过了,但运行阶段可能出现精度损失,谨慎使用。
接下来我们一起来看看精度损失的情况:
运行结果如下图所示:
图4-7:精度损失
4个字节的int类型300强转为1个字节的byte类型,最终的结果是44,为什么呢?首先300对应的二进制码是:00000000 00000000 00000001 00101100,强制类型转换的时候会变成1个字节,这个时候底层是将前3个字节砍掉了,也就是最后的二进制码是:00101100,这个二进制码对应的是44。
接下来我们再来看一下如果精度损失之后成为负数的情况:
public class IntegerTypeTest03 {
public static void main(String[] args) {
int a = 300;
byte b = (byte)a;
System.out.println("b = " + b);
}
}
运行结果如下图所示:
图4-8:精度损失
为什么以上的运行结果是-106呢?那是因为计算机在任何情况下都是采用二进制补码的形式存储数据的(至于为什么采用二进制补码形式存储数据,这里就不再赘述了,毕竟我们不是做学术研究)。
计算机二进制编码方式包括原码、反码、补码。对于正数来说原码、反码、补码是同一个。对于负数来说呢?负数的反码是在其原码的基础上, 符号位不变,其余各个位取反,例如:-15的原码是:10001111,-15反码是:11110000。负数的补码是其反码再加1。例如:-15的补码是11110000加1:11110001。换句话说-15最终在计算机上会采用11110001二进制来表示。
我们再来看看以上的程序:int a = 150。4个字节的150对应的二进制是:00000000 00000000 00000000 10010110,强转时前3个字节砍掉,最终计算机存储的二进制为:10010110,我们之前说过最终存储在计算机中的是二进制补码形式,也就是说10010110现在是二进制补码形式,我们通过补码推出原码,负数的补码是反码+1,所以10010110减1就是反码10010101,反码的符号位不变,其余位取反就能得出原码:11101010,而这个值就是-106。
接下来我们再来看一段程序,分析以下程序错在哪里,为什么以及怎么解决?
public class IntegerTypeTest05 {
public static void main(String[] args) {
long num = 2147483648;
}
}
编译报错了:
图4-9:编译错误提示信息
以上程序编译报错的原因是:java程序见到2147483648这个整数的时候,默认将其当做int类型来处理,但这个数字本身已经超出了int类型的取值范围,所以编译报错了,注意:这里编译报错的原因并不是说long类型存不下,long类型的变量完全可以存储这个数字,以上程序出现的错误是在赋值之前,还没有进行到赋值运算,数字本身已经超出int类型范围,自己崩掉了。怎么解决以上的问题呢?其实很简单,我们只要让java程序认为2147483648是一个long类型的数据就行了,也就是说在该数字后面添加L问题就解决了(long num = 2147483648L;)。
再来看一看整数类型还有没有其它的知识点要学习,请看以下程序:
public class IntegerTypeTest06 {
public static void main(String[] args) {
byte b = 127;
short s = 32767;
char c = 65535;
byte b1 = 128;
short s1 = 32768;
char c1 = 65536;
}
}
编译报错了:
图4-10:编译错误提示信息
通过以上测试,大家需要记住一个结论:当一个整数型的字面量没有超出byte,short,char的取值范围,可以将该字面量直接赋值给byte,short,char类型的变量。