【精致Java教程】10:常量、变量与运算符(一)

说到程序怎么能离得开数据呢。这篇文章和接下来几篇文章讲讲Java中数据的存储方式。
首先要明白常量和变量的概念。

常量##

任何一个“字面值”都是常量。例如数字1、1024,3.14,字母'a',符号'@',单词"hello",汉字“我”,句子"are you ok",布尔值true都是常量。
常量按类型划分为


这里有个问题,编译器是怎么知道一个值到底是什么类型的常量呢?例如1024到底是个整型还是个字符串?
答案是根据这个值在代码里有没有用单引号'或者双引号"包起来。数值型常量和逻辑常量不需要用引号包起来。逻辑常量只有true和false两个,数值型根据有无小数点再分为整型和实型。而用单引号包起来的是字符型,用双引号包起来的是字符串。例如1024是整型,而"1024"是字符串,'@'是字符,而"@"是字符串。

变量##

当程序运行时,数据是临时存储在内存中的。每个数据都需要在内存划出一块区域,而这一块一块的内存区域,称为变量。所以当你看到变量这个词时,要联想到的不是一个数字或者一个字符,而是一块内存区域。
变量有三个属性,<code>变量名</code>,<code>数据类型</code>和<code>作用域</code>。通过变量名来访问这块内存区域,数据类型包含了这块内存区域可以存储什么类型的数据和内存大小这两个信息,而作用域指的是代码中哪部分可以访问这块内存区域。
Java是一门强类型的语言。所谓强类型指的是每个变量或者说你在内存开辟每块数据区域必须先确定数据类型,确定了之后只能存储这个类型的数据。Java中数据类型按存储方式可以分为<code>基础属性类型</code>和<code>引用数据类型</code>两种。其中基础数据类型有八种,如下图。而引用数据类型因为可以自定义也就是说有无限种,其中字符串String就是一种引用数据类型。


数值型变量的声明和初始化##

现在我们先来看看基础数据类型中的数值型。也就是整数型:byte、short、int、long和实数型:float、double。他们都是用于表示数字,区别是所占用的字节数和表示范围不同,具体如下表。


上表已经很直观的说明了6种数值型变量的区别,这里就不再赘述。这里需要讲的是变量的使用方法。

变量的使用方法是先声明后初始化(或者叫赋值)。
声明方法是:<code>数据类型 变量名;</code>
例如:

byte b;
short s;
int i;
long l;

float f;
double d;

初始化方法是:<code>变量名 = 变量值;</code>
例如:

b = 127;
s = -32768;
i = 2147483647;
l = -2147483648;

f = 3.141592653F;
d = -3.141592653;

但是声明和初始化通常会合并成一个语句,也就是:<code>数据类型 变量名 = 变量值;</code>
例如:

byte b = 127;
short s = -32768;
int i = 2147483647;
long l = -2147483648;
     
float f = 3.141592653F;
double d = -3.141592653;

未经初始化的变量不能使用##

关于初始化还有一点需要注意,就是变量必须初始化以后才能使用。
例如下面这样只声明不初始化就会报错:

int i;
System.out.println(i);

<pre>
DataType.java:37: 错误: 可能尚未初始化变量i
System.out.println(i);
^
1 个错误
</pre>

取值范围问题##

取值范围其实就是变量不能存超过自身类型取值范围的值。
在上面的float f = 3.141592653F;中,注意看小数后面有个F。我如果把F去掉,编译时会出现精度丢失的错误。
<pre>
DataType.java:41: 错误: 不兼容的类型: 从double转换到float可能会有损失
float f = 3.141592653; // 默认把浮点型当做double,需要在后面加F
^
</pre>

原因是在Java中所有小数常量默认是double,且不会自动转换为float。而f是被声明为4个字节的float的,而3.141592653默认类型是8个字节的double。所以这次赋值无法通过,所以要主动告诉编译器把3.141592653当float处理,方法是在小数后面加个字母F(小写f也行)。

和Java把所有小数常量默认当作double一样,Java中所有整数常量当作int处理。但是如果把int赋值给byte和short编译并不会出错,因为只要不超出取值范围,在对byte和short赋值时编译器会把int当做byte和short处理。但是赋值给long并不会把int当做long,但是尽管如此编译时也不会出错,因为long的取值范围大于int。像下面这样是可以的:

byte b = 127;
short s = -32768;
int i = 2147483647;
long = 2147483647;

以上说的是不超出取值范围的情况,如果超出怎么办呢?
例如以下代码编译时会出现错误。

byte b = 128;
short s = -32769;
int i = 2147483648;

<pre>
DataType.java:52: 错误: 不兼容的类型: 从int转换到byte可能会有损失
byte b = 128;
^
DataType.java:53: 错误: 不兼容的类型: 从int转换到short可能会有损失
short s = -32769;
^
DataType.java:54: 错误: 过大的整数: 2147483648
int i = 2147483648;
^
</pre>

出现这种超出取值范围的错误,只能把值改小或者换更大的数据类型来存储了,例如把byte改成short,把short改成int,把int改成long。
除了这些还有一种情况没说,就是Java默认把整数当做int,如果需要使用的值大于int的取值范围怎么办?首先当然是把数据类型换成long。
例如:
<pre><code>
long l = 2147483648;
</code></pre>

但是编译又出错了:
<pre>
DataType.java:59: 错误: 过大的整数: 2147483648
long l = 2147483648; // 整形常数大于int的取值范围要在后面加L转为long
^
</pre>

原因还是因为Java默认把整数当int处理了,而int无法存储2147483648。所以只能主动的告诉编译器把某个整数当作long处理,方法就是在数字后面加字母L(小写l也行,但是强烈建议用大写,因为小写l和数字1很像)。
例如:
<pre><code>
long l = 2147483648L;
</code></pre>

好了,这篇文章看完你对常量、变量有个初步的了解。并且学会了数值型变量的声明和初始化。

本文代码下载:百度网盘

推荐阅读更多精彩内容