变量是一个语言中最基本的东西,在Java中也不例外。在变量命名方面,Java允许以字母、下划线、$开头,但是通常只以小写字母开头,而且很少使用下划线、$符号。另外,需要认真看一看Java的关键字和保留字,经常见笔试题上问,const是不是Java的关键字这类问题,所以还是需要适当注意一下。
接下来就是Java的变量类型,Java的变量类型一共有8种原始数据库型:byte, short, int, long, float, double, boolean, char。
byte类型
8位二进制位表示的有符号整数,这里需要强调是有符号整数。
byte的表示范围是-128到127,因为对于正数来说,最大值表示为0111 1111,其中第一位为符号位,0表示正数,后面7个1表示数值,恰好表示127 。而对于负数而言,为什么最小值是-128呢?
因为计算机中用补码来表示负数,求一个负数的补码的方法:首先写出负数的原码,如-127可以表示为1111 1111,其中第一个位的1代表符号位,首先将除符号位外的各位取反得到000 0000,然后在这个数上加1,即得到000 0001,然后再加上符号位就得到这个数的补码:1000 0001。
用同样方法可以求出-126的补码为1000 0010,-1的补码为1111 1111,由此我们可以看出,对于负数,后七位越小则表示的负数越大,所以最大负数应该为1000 0000,那么它到底表示是多少呢?我们把除符号位的7位按位取反再加1得到该数的原码:000 0000取反111 1111,再加1得1000 0000,这个数正好是128,所以最小值为-128 。
short类型
用16位二进制有符号整数表示,推导short表示范围与byte相似,这里就不在介绍了。
int类型
用32位二进制有符号整数表示,它是整数的缺省表示方法,但是这里需要强调一下类型自动升级及强制降级所发生的事情。
如:
byte num1 = -126;
int num2 = num1;
这时num1就会出现类型自动升级的情况,如下所示:
-126的补码为1000 0010
而类型升级时规则为符号位自动向高位扩展,即:1111 1111 1111 1111 1111 1111 1000 0010,通过求这个数的原码为*000 0000 0000 0000 0000 0000 0111 1110,其值正好为126,再加上符号,即表示为-126,这是没有问题的。
但是如果是强制降级的话就有可能出现问题,如下所示:
int num1 = -132;
byte num2 = (byte)num1;
这时-132的int型表示为:000 0000 0000 0000 0000 0000 1000 0100
按位取反加1得补码:111 1111 1111 1111 1111 1111 0111 1100 <= ( 0111 1011+1)
再前边加上符号位:1111 1111 1111 1111 1111 1111 0111 1100
将其强制转换为byte时,值变为:0111 1100
上边的值为变成了正的124,不但值变了,而且还改变了符号。
综上所述,这种强制的类型转换是非常危险的,需要十分慎重才行。
long类型
8字节表示的整数。
float类型
32位表示的单精度数。由于小数缺省都是double型的,因此需要在小数后面加上后缀f表示其为float型。
double类型
64位表示的双精度数。
对于double型(包括float型),需要特别注意其表示小数时是不精确的,因此如果进行精确的运算时,需要格外注意。不光如此,即使进行普通的计算,也要注意这个问题。比如下面的程序:
double num1 = 0.1;
double num2 = 0.2;
System.out.println("num1+num2=" + (num1+num2) + "!");
运行这个程序,其输出结果为:num1+num2=0.30000000000000004,而不是我们理所当然认为的0.3。如果此时我们用if (0.3 == num1+num2)来判断的话,那么结果将永远为假,与我们希望的结果非常不一致。
boolean类型
仅有两个值true或false,但是存储空间是不定的。
char类型
16位Unicode字符,\u0000到\uffff,表示65536个字符。